错误乘以大的双打

时间:2014-06-14 21:29:06

标签: c++ math double

我用C ++制作了一个使用双打的BOMDAS计算器。每当我输入像

这样的表达式时
1000000000000000000000*1000000000000000000000

我得到的结果如1000000000000000000004341624882808674582528.000000。我怀疑它与浮点数有关。

3 个答案:

答案 0 :(得分:0)

浮点数表示具有固定大小表示的值。 double可以表示16位十进制数字,其中可以恢复十进制数字(在内部,它通常使用基数2存储该值,这意味着它可以准确地表示大多数小数十进制值)。如果超过位数,则将适当地舍入该值。当然,结果是你不一定得到你希望的数字:如果你明确地或隐含地要求超过16位十进制数字(例如通过将格式设置为std::ios_base::fixed的数字,大于1e16)格式化将会产生更多的数字:它将准确地表示内部保持的二进制值,我认为这可能产生54个非零数字。

如果要精确计算大值,则需要一些可变大小的表示。由于您的值是整数,因此可以使用大整数表示。与double相比,计算速度通常要慢得多。

答案 1 :(得分:0)

双重存储53位精度。这大约是15位小数。您的问题是double无法存储您尝试存储的位数。第15位十进制数后的数字将不准确。

答案 2 :(得分:0)

这不是错误。这正是由于浮点类型的表示方式,因为结果精确到double精度。

计算机中的浮点类型以( - 1) sign * mantissa * 2 exp 的形式编写,因此它们只有<强>范围更广,而不是无限精度。它们仅精确到尾数精度,并且每次操作后的结果将被舍入。 double类型最常被实现为IEEE-754 64位双精度,具有53位尾数,因此记录(2 53 )≈15.955十进制数字是正确的。执行1e21*1e21会产生1e42,当以二次精度四舍五入到最接近的值时,会得到您看到的值。如果将其四舍五入为16位,则与1e42完全相同。

如果您需要更多范围,请使用doublelong double。如果你只使用整数,那么int64_t(或__int128与gcc和64位平台上的许多其他编译器)具有更大的精度(64/128位与53位相比)。如果您需要更加精确,请使用arbitrary-precision arithmetic库,例如GMP