错误乘以大倍数 我用C++编写了一个使用双倍的BoMDA计算器。每当我输入一个表达式,比如 1000000000000000000000*1000000000000000000000

错误乘以大倍数 我用C++编写了一个使用双倍的BoMDA计算器。每当我输入一个表达式,比如 1000000000000000000000*1000000000000000000000,c++,math,floating-point,double,C++,Math,Floating Point,Double,我得到的结果是10000000000000000004341624882808674582528.000000。我怀疑它与浮点数有关。浮点数用固定大小表示值。double可以表示16个十进制数字,其中十进制数字可以在内部恢复,它通常使用基数2存储值,这意味着它可以准确地表示大多数十进制分数。如果超过位数,则该值将适当四舍五入。当然结果是,你不一定能得到你想要的数字:如果你明确或隐含地要求超过16位十进制数字,例如,通过将格式设置为std::ios_base::fixed,使用大于1e16的数字,

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

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


如果您想精确地计算大值,您需要一些可变大小的表示。因为您的值是整数,所以大整数表示可能会起作用。使用double进行计算通常要慢得多。

一个double存储53位精度。这大约是15位小数。您的问题是double无法存储您试图存储的位数。第15位小数后的数字将不准确。

这不是错误。这完全是因为浮点类型是如何表示的,因为结果是精确到双精度的

计算机中的浮点类型是以-1sign*尾数*2exp的形式编写的,因此它们只有更宽的范围,而不是无限精度。它们只精确到尾数精度,每次运算后的结果都会四舍五入。double类型最常见的实现方式是IEEE-754 64位双精度,尾数为53位,因此可以将其更正为log253≈ 15.955位小数。执行1e21*1e21生成1e42,当以双精度舍入到最接近的值时,会给出您看到的值。如果将其四舍五入到16位,则与1e42完全相同


如果你需要更大的射程,可以使用双人或长双人。如果您只使用integer,那么使用gcc的int64_t或int128以及64位平台上的许多其他编译器的64/128位精度要比53位高很多。如果您需要更高的精度,请使用库,例如

@mc110谢谢您的编辑,bro:有更多关于浮点精度限制的相关信息-如果您在计算器中使用FP表示,您将不得不预期您将看到此类问题。或者@mc110基本上,我必须学会接受这个?@SkyLightna如果你不得不接受双打,你只需要接受这个。对于其他类型,你可以获得无限的精度。因此,如果我以某种方式将双精度的大小限制为15位,我会得到更精确的结果吗?@SkyLightna不,将两个15位数字相乘会得到一个30位数字。您将只获得结果的前15位,或者更精确地说是53位correctly@LưuVĩnhPhúc,这样我就可以将结果转换为字符串,并将其截断,使其符合精确限制,然后将其转换回双精度?不,不管字符串可以存储多高的精度,转换回双精度后,它只能存储最高15位有效数字。就像我说的,如果适合的话,使用int64\u t\u\u int128\u t,否则需要使用任意精度的算术。更不用说字符串效率极低,在64位系统中,库将使用基数2^32或2^64,而不是基数10。如果使用字符串,则实际上,错误是近似值和实际值之差的数学术语。这是一个错误。