我用C ++制作了一个使用双打的BOMDAS计算器。每当我输入一个表达式时
1000000000000000000000*1000000000000000000000
我得到的结果如1000000000000000000004341624882808674582528.000000。我怀疑它与浮点数有关。
浮点数表示具有固定大小表示的值。 double
可以表示16位十进制数字,其中十进制数字可以恢复(在内部,它通常使用基数2存储值,这意味着它可以准确地表示大多数小数十进制值)。如果超过位数,则将适当地舍入该值。当然,结果是你不一定会得到你希望的数字:如果你明确地或隐含地要求超过16位十进制数字(例如通过将格式设置为std::ios_base::fixed
,其数字大于1e16
)格式化将会产生更多的数字:它将准确地表示内部保持的二进制值,我认为这可能产生54个非零数字。
如果要精确计算大值,则需要一些可变大小的表示。由于您的值是整数,因此可以使用大整数表示。与double
相比,计算速度通常要慢得多。
双精度存储53位。这大约是15位小数。您的问题是double无法存储您尝试存储的位数。十五位数后的数字将不准确。
那不是错误。这正是由于浮点类型的表示方式,因为结果精确到double
精度。
计算机中的浮点类型以(-1)符号*尾数* 2exp的形式写入,因此它们只有更宽的范围,而不是无限的精度。它们仅精确到尾数精度,并且每次操作后的结果将被舍入。 double
类型最常用的是IEEE-754 64位双精度和53位尾数,所以它可以正确记录(253)≈15.955十进制数字。做1e21*1e21
会产生1e42
,当以double精度舍入到最接近的值时,会给出你看到的值。如果将其四舍五入为16位,则与1e42完全相同。
如果您需要更多射程,请使用double
或long double
。如果你只使用整数,那么int64_t
(或者带有gcc的__int128
和64位平台上的许多其他编译器)具有更大的精度(64/128位与53位相比)。如果您需要更高的精度,请使用arbitrary-precision arithmetic库,例如GMP