---
title: 数学
description: Tact 核心库中的各种数学辅助函数
---

各种数学辅助函数

## min

```tact
fun min(x: Int, y: Int): Int;
```

计算并返回两个 [`Int{:tact}`][int]值 `x` 和 `y` 的 [最小值](https://en.wikipedia.org/wiki/Maximum_and_minimum)。

使用示例

```tact
min(1, 2);        // 1
min(2, 2);        // 2
min(007, 3);      // 3
min(0x45, 3_0_0); // 69, nice
//  ↑     ↑
//  69    300
```

## max

```tact
fun max(x: Int, y: Int): Int;
```

计算并返回两个 [`Int{:tact}`][int]值 `x` 和 `y` 的 [最大值](https://en.wikipedia.org/wiki/Maximum_and_minimum)。

使用示例：

```tact
max(1, 2);        // 2
max(2, 2);        // 2
max(007, 3);      // 7
max(0x45, 3_0_0); // 300
//  ↑     ↑
//  69    300
```

## abs

```tact
fun abs(x: Int): Int
```

计算并返回[`Int{:tact}`][int]值 `x` 的[绝对值](https://en.wikipedia.org/wiki/Absolute_value)。

使用示例：

```tact
abs(42);        // 42
abs(-42);       // 42
abs(-(-(-42))); // 42
```

## log

```tact
fun log(num: Int, base: Int): Int;
```

计算并返回数字 `num` $> 0$ 以 `base` $≥1$ 为底的 [logarithm](https://en.wikipedia.org/wiki/Logarithm) 值。 结果[四舍五入](https://en.wikipedia.org/wiki/Rounding#Rounding_down)。 传入一个非正数 `num` 值或 `base` 小于 $1$ 会产生错误[退出码 5](/zh-cn/book/exit-codes#5)：`Integer out of expected range`。

示例用法：

```tact
log(1000, 10); // 3, as 10^3 is 1000
//  ↑     ↑             ↑       ↑
//  num   base          base    num

log(1001, 10);  // 3
log(999, 10);   // 2
try {
  log(-1000, 10); // throws exit code 5 because of the non-positive num
}
log(1024, 2);   // 10
try {
  log(1024, -2);  // throws exit code 5 because of the base less than 1
}
```

:::note

  请注意，如果只需要获取以 $2$为底的对数，请使用 [`log2(){:tact}`](#log2)函数，因为它更省 gas。

:::

## log2

```tact
fun log2(num: Int): Int;
```

类似于 [`log(){:tact}`](#log)，但将 `base` 设为 $2$。

示例用法：

```tact
log2(1024); // 10, as 2^10 is 1024
//   ↑                ↑       ↑
//   num              base₂   num
```

:::note

  为了减少 gas 用量，当您只需要获取以 $2$为底的对数时，最好使用该函数，而不是调用 [`log(){:tact}`](#log)。

:::

## pow

```tact
fun pow(base: Int, exp: Int): Int;
```

计算并返回涉及两个数字的 [指数运算](https://en.wikipedia.org/wiki/Exponentiation)：`base` 和指数（或 _幂_）`exp`。 指数 `exp` 必须是非负数，否则将产生[退出码 5](/zh-cn/book/exit-codes#5)错误：`Integer out of expected range`。

请注意，该函数在运行时和[编译时](/zh-cn/ref/core-comptime)均有效。

示例用法：

```tact
contract Example {
    // Persistent state variables
    p23: Int = pow(2, 3); // raises 2 to the 3rd power, which is 8
    one: Int = pow(5, 0); // raises 5 to the power 0, which always produces 1
                          // works at compile-time!

    // Internal message receiver, which accepts message ExtMsg
    receive() {
        pow(self.p23, self.one + 1); // 64, works at run-time too!
        pow(0, -1);                  // ERROR! Exit code 5: Integer out of expected range
    }
}
```

:::note

  注意，如果只需要获取 $2$的幂，请使用 [`pow2(){:tact}`](#pow2)函数，因为它更省 gas。

:::

:::note

  仅在编译时工作的函数列表：[API Comptime](/zh-cn/ref/core-comptime)。

:::

## pow2

```tact
fun pow2(exp: Int): Int;
```

与 [`pow(){:tact}`](#pow) 类似，但将 `base` 设为 $2$。 在运行时和 [编译时](/zh-cn/ref/core-comptime) 均可使用。

示例用法：

```tact
contract Example {
    // Persistent state variables
    p23: Int = pow2(3); // raises 2 to the 3rd power, which is 8
    one: Int = pow2(0); // raises 2 to the power 0, which always produces 1
                        // works at compile-time!

    // Internal message receiver, which accepts message ExtMsg
    receive() {
        pow2(self.one + 1); // 4, works at run-time too!
        pow2(-1);           // ERROR! Exit code 5: Integer out of expected range
    }
}
```

:::note

  为了减少 gas 用量，当您只需要获取 $2$的幂时，最好使用该函数，而不是调用 [`pow(){:tact}`](#pow) 。

:::

:::note

  仅在编译时工作的函数列表：[API Comptime](/zh-cn/ref/core-comptime)。

:::

## checkSignature

```tact
fun checkSignature(hash: Int, signature: Slice, public_key: Int): Bool;
```

检查 $256$ 位无符号 [`Int{:tact}`][int] `hash` 的 [Ed25519][ed] `signature`，使用 `public_key`，它也是一个 $256$ 位无符号 [`Int{:tact}`][int]。 签名必须包含至少 $512$ 位数据，但只使用前 $512$ 位。

如果签名有效，则返回 `true{:tact}`，否则返回 `false{:tact}`。

示例用法：

```tact {19-24}
message ExtMsg {
    signature: Slice;
    data: Cell;
}

contract Showcase {
    // Persistent state variables
    pub: Int as uint256; // public key as an 256-bit unsigned Int

    // Constructor function init(), where all the variables are initialized
    init(pub: Int) {
        self.pub = pub; // storing the public key upon contract initialization
    }

    // External message receiver, which accepts message ExtMsg
    external(msg: ExtMsg) {
        let hash: Int = beginCell().storeRef(msg.data).endCell().hash();
        let check: Bool = checkSignature(hash, msg.signature, self.pub);
        //                               ----  -------------  --------
        //                               ↑     ↑              ↑
        //                               |     |              public_key, stored in our contract
        //                               |     signature, obtained from the received message
        //                               hash, calculated using the data from the received message
        // ... follow-up logic ...
    }
}
```

## checkDataSignature

```tact
fun checkDataSignature(data: Slice, signature: Slice, public_key: Int): Bool;
```

检查 `data` 的 [Ed25519][ed] `signature`，使用 `public_key`，类似于 [`checkSignature(){:tact}`](#checksignature)。 如果 `data` 的位长不能被 $8$整除，该函数将产生错误[退出码 9](/zh-cn/book/exit-codes#9)：`Cell underflow`。 验证本身是间接进行的：根据  `data` 的[SHA-256][sha-2] 哈希值进行验证。

如果签名有效，则返回 `true{:tact}`，否则返回 `false{:tact}`。

示例用法：

```tact
let data: Slice = some_data;
let signature: Slice = some_signature;
let publicKey: Int = 42;

let check: Bool = checkSignature(data, signature, publicKey);
```

## sha256

```tact
fun sha256(data: Slice): Int;
fun sha256(data: String): Int;
```

从传递的 [`Slice{:tact}`][slice] 或 [`String{:tact}`][p]`data`计算[SHA-256][sha-2] 哈希值，并以 $256$-bit 无符号 [`Int{:tact}`][int]的形式返回。

如果 `data` 是一个 [`String{:tact}`][p]，它的位数应能被 $8$除，如果它是一个 [`Slice{:tact}`][slice]，它**也必须**没有引用（即总共只有最多 $1023$ 位数据）。 该函数尽可能在 [编译时](/zh-cn/ref/core-comptime) 解析常量字符串值。

:::caution

  如果[`String{:tact}`][p] 值在[编译时间](/zh-cn/ref/core-comptime)期间无法解析，则哈希值是由 [TVM][tvm] 本身在运行时计算的。 注意，通过 [TVM][tvm] 对超过 $128$ 字节的字符串进行哈希处理时，如果它们的前 $128$ 字节相同，可能会导致碰撞。

  因此，选择尽可能使用静态的字符串。 如有疑问，请使用长度不超过 $128$ 字节的字符串。

:::

使用示例：

```tact
sha256(beginCell().asSlice());
sha256("Hello, world!"); // will be resolved in compile-time
sha256(someVariableElsewhere); // will try to resolve at compile-time,
                               // and fallback to run-time evaluation
```

[p]: /zh-cn/book/types#primitive-types
[bool]: /zh-cn/book/types#booleans
[int]: /zh-cn/book/integers
[slice]: /zh-cn/book/cells#slices
[tvm]: https://docs.ton.org/learn/tvm-instructions/tvm-overview
[ed]: https://en.wikipedia.org/wiki/EdDSA#Ed25519
[sha-2]: https://en.wikipedia.org/wiki/SHA-2#Hash_standard
