首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >分式数指数函数

分式数指数函数
EN

Ethereum用户
提问于 2020-02-16 15:47:59
回答 2查看 2.9K关注 0票数 6

在坚实的情况下,我们不能直接计算0.1或0.001。我们通常使用十进制乘数和除数整数来计算如下数字:

代码语言:javascript
复制
0.01 = 1 / 100

当数字大于1时,比较容易,因为我们只是重复乘法:

代码语言:javascript
复制
function(uint base, uint exponent) external {
    for (uint256 i = 1; i < exponent; i++) 
        uint256 z = base;
        z = z * base; 
    }

或者只是:

代码语言:javascript
复制
z ** exponent

然而,当我们想使用分数阶数作为指数时,这些函数就不能工作了。有人能想出一个好办法吗?

EN

回答 2

Ethereum用户

发布于 2021-04-02 16:20:24

二元分数

我目前只知道一种解决方案,由米哈伊尔符拉迪米罗夫编写。它以二进制分数的形式计算输入。

ABDKMath64x64.sol有一个exp_2函数,如下所示:

代码语言:javascript
复制
function exp_2(int128 x) internal pure returns (int128) {
    unchecked {
        require(x < 0x400000000000000000); // Overflow

        if (x < -0x400000000000000000) return 0; // Underflow

        uint256 result = 0x80000000000000000000000000000000;

        // REMOVED: Binary fraction logic, explained below...

        result >>= uint256(int256(63 - (x >> 64)));
        require(result <= uint256(int256(MAX_64x64)));

        return int128(int256(result));
    }
}

为了简洁起见,我跳过了函数体的一大部分。

解释

任何小数都可以写成整数部分和分数部分的之和:

代码语言:javascript
复制
x = n + f, 0 <= f < 1

然后,使用x作为指数:

代码语言:javascript
复制
y = 2^x = 2^(n + f) = 2^n * 2^f;

注意到我们可以将f写成一个二元分数

代码语言:javascript
复制
f = f1 * 2^-1 + f2 * 2^-2 + ...

其中f_i可以是0或1。然后:

代码语言:javascript
复制
y = 2^n * (2^(f1*2^-1) * 2^(f2*2^-2) ...)

请注意:

代码语言:javascript
复制
for f_i = 0 => 2^(f_i * 2^-i) = 1
for f_i = 1 => 2^(f_i * 2^-i) = root(2, 2^i)

因此,我们预先计算了这些root(2, 2^-i)魔术因子,并使用它们作为硬编码常量。i表示位在小数二进制表示中的位置。如果我们要匹配第一位,我们将乘以2的平方根,即~1.4142。

任意基

根据基本对数规则:

代码语言:javascript
复制
x = b^(log_b(x))

我们可以推断:

代码语言:javascript
复制
x^y = b^(y*log_b(x))

适用于基地2:

代码语言:javascript
复制
x^y = 2^(y*log_2(x))

我们已经为exp_2提供了一个实现,日志_2也由ABDKMath64x64提供。

权衡

我不喜欢米哈伊尔的解决方案:

  1. 要求用户使用二进制数字。
  2. 精度仅限于int128,不适用于int256或其附近
票数 5
EN

Ethereum用户

发布于 2021-07-01 05:53:30

保罗的回答很好。如果你想逼近指数函数,我用了一系列的线性函数,目标半衰期:

代码语言:javascript
复制
function getPrice(uint256 value, uint256 t, uint256 halfLife) public pure returns (uint256 price) {
    price = value >> (t / halfLife);
    price -= price * (t % halfLife) / halfLife / 2;
}

在我的代码中,半衰期是两天内的秒数。

票数 4
EN
页面原文内容由Ethereum提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://ethereum.stackexchange.com/questions/79903

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档