double -> long
double の値を long にキャストした時,VC 8 で思った動作ではなかったので調べてみた.
テストに使用したのは次の様な単純なコード.
// T_DtoI.cpp
#include <iostream>
int main(int argc, char* argv[])
{
double d8 = 1/7. ;
for (int index=0 ; index<25 ; index++) {
d8 = (d8 * 7) ;
__int64 i8 = __int64(d8) ;
long l4 = long(d8) ;
printf ((“%15g\t%25I64d\t%20I64x\t%15ld\t%15x\n”),d8,i8,i8,l4,l4) ;
}
return 0;
}
d8 の値を /7 と *7 としているのはあまり意味はない.
C:\Users\Iwao>\\DevXP\C_Drive\Temp\TestCPP\T_DtoI\Release.060\T_DtoI.exe 1 1 1 1 1 7 7 7 7 7 49 49 31 49 31 343 343 157 343 157 2401 2401 961 2401 961 16807 16807 41a7 16807 41a7 117649 117649 1cb91 117649 1cb91 823543 823543 c90f7 823543 c90f7 5.7648e+006 5764801 57f6c1 5764801 57f6c1 4.03536e+007 40353607 267bf47 40353607 267bf47 2.82475e+008 282475249 10d63af1 282475249 10d63af1 1.97733e+009 1977326743 75db9c97 1977326743 75db9c97 1.38413e+010 13841287201 339014821 956385313 39014821 9.6889e+010 96889010407 168f08f8e7 -1895237401 8f08f8e7 6.78223e+011 678223072849 9de93ece51 -381759919 e93ece51 4.74756e+012 4747561509943 45160b7a437 1622647863 60b7a437 3.32329e+013 33232930569601 1e39a5057d81 -1526366847 a5057d81 2.32631e+014 232630513987207 d39383266e87 -2094633337 83266e87 1.62841e+015 1628413597910449 5c908960d05b1 -1777531471 960d05b1 1.13989e+016 11398895185373144 287f3c1a5b27d8 442181592 1a5b27d8 7.97923e+016 79792266297612000 11b7aa4b87e16e0 -1199696160 b87e16e0 5.58546e+017 558545864083283968 7c05a810b72a000 192061440 b72a000 3.90982e+018 3909821048582987776 3642798750226000 1344430080 50226000 2.73687e+019 -9223372036854775808 8000000000000000 0 0 1.91581e+020 -9223372036854775808 8000000000000000 0 0 C:\Users\Iwao>\\DevXP\C_Drive\Temp\TestCPP\T_DtoI\Release.080\T_DtoI.exe 1 1 1 1 1 7 7 7 7 7 49 49 31 49 31 343 343 157 343 157 2401 2401 961 2401 961 16807 16807 41a7 16807 41a7 117649 117649 1cb91 117649 1cb91 823543 823543 c90f7 823543 c90f7 5.7648e+006 5764801 57f6c1 5764801 57f6c1 4.03536e+007 40353607 267bf47 40353607 267bf47 2.82475e+008 282475249 10d63af1 282475249 10d63af1 1.97733e+009 1977326743 75db9c97 1977326743 75db9c97 1.38413e+010 13841287201 339014821 -2147483648 80000000 9.6889e+010 96889010407 168f08f8e7 -2147483648 80000000 6.78223e+011 678223072849 9de93ece51 -2147483648 80000000 4.74756e+012 4747561509943 45160b7a437 -2147483648 80000000 3.32329e+013 33232930569601 1e39a5057d81 -2147483648 80000000 2.32631e+014 232630513987207 d39383266e87 -2147483648 80000000 1.62841e+015 1628413597910449 5c908960d05b1 -2147483648 80000000 1.13989e+016 11398895185373144 287f3c1a5b27d8 -2147483648 80000000 7.97923e+016 79792266297612000 11b7aa4b87e16e0 -2147483648 80000000 5.58546e+017 558545864083283968 7c05a810b72a000 -2147483648 80000000 3.90982e+018 3909821048582987776 3642798750226000 -2147483648 80000000 2.73687e+019 -9223372036854775808 8000000000000000 -2147483648 80000000 1.91581e+020 -9223372036854775808 8000000000000000 -2147483648 80000000
VC 7 , 7.1 は VC 6 と同等.VC 12 までは VC 8 と同等.
Mac 64 ビットでは,long が 64 ビットのため?そのままだと VC 6 と同等になる.
long を int として 32 ビットとすると VC 8 と同等.
ここまでは,long の範囲を超えたためと理解できるが,unsigned long の場合はまた動作が異なる.
long l4 = long(d8) ;
ULONG u4 = ULONG(d8) ;
printf ((“%15g %25I64d %20I64x %12ld %10x %12ld %10x\n”),d8,i8,i8,l4,l4,u4,u4) ;
今回表面化したバグは,次のコード.
long now_Tick = long(GetTickCount_s()*1000) ;
得た値を覚えておき,次のタイミングで 1 秒以上の開きがあるかを計測したかった.
最初の頃はわからなかったが,
先日 25 日(0x7FFFFFFF 2,147,483,647)を過ぎて 0x80000000 となってしまっていた.
MSDN 浮動小数点型からの変換