C++ C++;将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

我注意到在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)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。请看,在你试着用大脑思考两个事实之后,你应该能够自己解决这个问题:1
sizeof(double)
sizeof(long-long)
相同。2)
double
似乎能够表示比long-long大得多的值,例如
1e100
,或1后跟100个零。现在,扪心自问,如果
long-long
double
都占用相同的字节数,那么你应该能够找到问题的答案。我只是想知道在加法之后,最终结果是否会存储在long-long中,为什么左侧默认转换为double,然后再转换为long?如果我希望在默认情况下不丢失精度,该怎么办。在复杂的代码中,可能有太多的地方去检查缺少显式的转换。这是C++算法的工作原理,必须始终牢记在心。这也是隐式转换是邪恶的原因。