这里有几个因素在起作用。最重要的1.0/3.0
是,不完全是三分之一,因此您没有计算base
. 相反,您指定的计算是:
base**0.333333333333333314829616256247390992939472198486328125
或者
exp(0.333333333333333314829616256247390992939472198486328125 * log(base))
当base
是125
时,该计算的准确实数结果为:
4.999999999999999553291243227753830961690873860134487744...
最接近该值的两个可表示双精度数是5.0
和:
4.99999999999999911182158029987476766109466552734375
后一个值几乎不接近数学上的精确结果,因此该pow
函数返回了可能的最佳(或“正确舍入”)答案。
当您使用base
等于 27 进行相同的计算时,数学上精确的实数结果是:
2.99999999999999981704430129767885583952101310176125736...
在这种情况下,这个数字比它更接近于3.0
任何其他可表示的双精度数,因此再次pow
返回了可能的最佳结果。
因此,在这些情况下,该pow
函数会为您提示的计算提供最准确的结果。现在,也就是说,不能保证pow
对所有可能的输入都这样做(实际上,通常情况下不会)。对于所有输入,您不会获得如此准确的结果,并且对于某些平台上的许多输入,您将获得明显不太准确的结果。通常,您不应依赖pow
函数的最后一位舍入,或任何未明确定义的函数以产生正确舍入的结果。
简而言之:你得到的结果是最好的结果,而在其他一些平台上你就不会那么幸运了。
备择方案:
您可能会考虑使用该cbrt
函数,它也不能保证正确的舍入,但至少是计算立方根而不是 0.3333333333333333148296...th 次方。
如果您先验地知道结果应该是整数,则可以通过round
orrint
函数将其四舍五入为最接近的整数。
如果您确实需要精确的最后一位舍入,请考虑使用 CRLibm 库。这会带来一些性能成本,但如果您绝对必须进行正确的舍入,这是唯一的好选择(但请注意,对于这些特定示例,它将产生完全相同的结果)。