从(unsigned long long)更改为(double)时发生错误。错误很小,只在某些数字中发生,但它就在那里。 MSVC和GCC中的错误相同。
检查自己:
#include <stdio.h>
int main( void )
{
long long a = 834146832894220100LL;
unsigned long long b = 834146832894220100ULL;
printf( "%.16f\n%.16f\n",
(( double )a / 1e+18),
(( double )b / 1e+18)
);
getchar( );
return 0;
}
结果是:
0.8341468328942201
0.8341468328942202
这是来自MSVC的asm代码:
// long long a = 834146832894220100LL;
mov dword ptr [a],12D5744h
mov dword ptr [ebp-20h],0B937C20h
// unsigned long long b = 834146832894220100ULL;
mov dword ptr [b],12D5744h
mov dword ptr [ebp-30h],0B937C20h
// This is unsigned to double conversion:
mov eax,dword ptr [b]
mov ecx,dword ptr [ebp-30h]
mov dword ptr [ebp-100h],eax
mov dword ptr [ebp-0FCh],ecx
mov edx,dword ptr [ebp-0FCh]
mov dword ptr [ebp-104h],edx
and dword ptr [ebp-0FCh],7FFFFFFFh
fild qword ptr [ebp-100h]
and dword ptr [ebp-104h],80000000h
mov dword ptr [ebp-108h],0
fild qword ptr [ebp-108h]
fchs
faddp st(1),st
fdiv qword ptr [__real@43abc16d674ec800 (0C07870h)]
mov esi,esp
sub esp,8
fstp qword ptr [esp]
// This is signed to double conversion:
fild qword ptr [a]
fdiv qword ptr [__real@43abc16d674ec800 (0C07870h)]
sub esp,8
fstp qword ptr [esp]
您有什么看法?
答案 0 :(得分:1)
我在i386上反汇编了gcc 4.9.1中生成的代码。它为每个产生了相同的确切代码。我猜你的编译器在内部进行不同的评估,具体取决于类型。您可以尝试不同的优化级别和/或更改已签名与未签名的顺序。 它也可能是printf代码中的一个错误,它与为转换为文本的第一个/其余部分设置舍入模式有所不同。