C++ C++;将double添加到long时的精度错误
我注意到在VisualStudio中将double添加到long时会出现精度错误。例如:C++ C++;将double添加到long时的精度错误,c++,precision,long-integer,assign,C++,Precision,Long Integer,Assign,我注意到在VisualStudio中将double添加到long时会出现精度错误。例如: long long a = 44981600439878676; double b = 234567890; a += b; a的结果为449816006746560,但应为449816006746566。x32和x64都会发生这种情况 但是,以下内容返回正确的值: long long a = 44981600439878676; double b = 234567890; a += (long long
long long a = 44981600439878676;
double b = 234567890;
a += b;
a的结果为449816006746560,但应为449816006746566。x32和x64都会发生这种情况
但是,以下内容返回正确的值:
long long a = 44981600439878676;
double b = 234567890;
a += (long long)b;
我在反汇编中注意到,在没有显式强制转换的第一种情况下,有
0116A892 call __ltod3 (011619DDh)
0116A897 addsd xmm0,mmword ptr [b]
0116A89C call __dtol3 (01161A05h)
而在第二种情况下,不调用u ltod3。我用VC++编译器来解释这一点,默认情况下先将long-long转换为double,然后再将double转换为long-long,因为double比long-long更简单。在这种情况下,由于uu ltod3和int64包含太大的值,我们会丢失精度。但从另一方面来说,a是l值,在这种情况下,因为编译器知道输出是长的,所以在加法过程中,似乎没有必要先将左侧转换为double,然后再转换为long-long。此外,有些人很容易犯错误并忽略显式强制转换,因为精度错误只对某些数字可见
是C++标准的双重转换部分,还是按照VS/< P>>P>标准:
形式为E1 op=E2的表达式的行为等效于 E1=E1 op E2,但E1仅计算一次 因此,即使最终结果可能再次需要转换回a
类型,通常的算术转换也适用(请参阅)
对于示例中的a+=b
,由a
转换为double
。加法是使用浮点运算来执行的。
对于您的特定值a
的精确整数值和加法结果的精确整数值不能用double
精确表示,因此结果是不精确的
使用a+=(long-long)b
时,两个操作数都是long-long
,因此不需要转换。加法是使用整数算法执行的
在您的特定示例中,
b
的值恰好在double
的精确表示范围内。因此,从整数文本到double
以及使用(long-long)b
返回到long
的转换恰好返回相同的值。因此,加法的结果就是精确的结果。double的精度不如long-long。请看,在你试着用大脑思考两个事实之后,你应该能够自己解决这个问题:1sizeof(double)
与sizeof(long-long)
相同。2) double
似乎能够表示比long-long大得多的值,例如1e100
,或1后跟100个零。现在,扪心自问,如果long-long
和double
都占用相同的字节数,那么你应该能够找到问题的答案。我只是想知道在加法之后,最终结果是否会存储在long-long中,为什么左侧默认转换为double,然后再转换为long?如果我希望在默认情况下不丢失精度,该怎么办。在复杂的代码中,可能有太多的地方去检查缺少显式的转换。这是C++算法的工作原理,必须始终牢记在心。这也是隐式转换是邪恶的原因。