【发布时间】:2020-10-28 07:51:49
【问题描述】:
假设uint是我的定点平台上最大的整数类型,我有:
uint func(uint a, uint b, uint c);
这需要返回a * b / c 的良好近似值。
c 的值大于a 的值和b 的值。
所以我们确定a * b / c 的值适合uint。
但是,a * b 的值本身会溢出uint 的大小。
所以计算a * b / c 值的一种方法是:
return a / c * b;
甚至:
if (a > b)
return a / c * b;
return b / c * a;
但是,c 的值大于a 的值和b 的值。
所以上面的建议只会返回零。
我需要按比例减少 a * b 和 c,但同样 - 问题是 a * b 溢出。
理想情况下,我能够:
- 将
a * b替换为uint(-1) - 将
c替换为uint(-1) / a / b * c。
但是无论我如何排序表达式uint(-1) / a / b * c,我都会遇到一个问题:
-
由于
uint(-1) / a / b,uint(-1) / a / b * c被截断为零 -
uint(-1) / a * c / b因uint(-1) / a * c而溢出 -
uint(-1) * c / a / b因uint(-1) * c而溢出
我该如何处理这种情况才能找到a * b / c 的良好近似值?
编辑 1
我的平台上没有_umul128之类的东西,当时最大的整数类型是uint64。我最大的类型是uint,我不支持比这更大的任何东西(无论是在硬件级别,也不在某些预先存在的标准库中)。
我最大的类型是uint。
编辑 2
针对众多重复的建议和cmets:
我手头没有一些“更大的类型”,我可以用它来解决这个问题。这就是为什么问题的开场白是:
假设
uint是我定点平台上最大的整数类型
我假设不存在其他类型,无论是在 SW 层(通过一些内置标准库)还是在 HW 层。
【问题讨论】:
-
好吧,
a或b必须大于“uint的一半”,所以也许我应该将其中较大的一个替换为,例如,auint(-1) / a。然后,我可以按比例修复c...只是一个想法... -
@GSerg:不,不是,谢谢。
-
@4386427: 精度优先,谢谢。
-
@vmp:C++ 在这里有何不同?这是一个纯算术问题。无论如何,我的问题甚至不在 C 语言中,而是在 Solidity 中。我发布它 C 的唯一原因是因为它的受众比 Solidity 的受众更多,而这两种语言具有相同的本机支持整数除法的共同性质(即,根据定义)。
标签: c integer integer-overflow integer-arithmetic