double -> long

投稿日 by Iwao

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 浮動小数点型からの変換

この投稿は役に立ちましたか? 役に立った 役に立たなかった 0 人中 0 人がこの 投稿 は役に立ったと言っています。

  にほんブログ村 IT技術ブログへ

  • カテゴリー:


コメントを残す

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください