• ベストアンサー

doubleからfloatへの変換でのトラブル

double test = 0.01; float test2 = (float)test; このプログラムを実行すると、test2には何故か「0.00999999998」という数字が入ってしまい、「0.01」にはなりません。正確にdoubleからfloatへキャストする方法はあるのでしょうか。 環境はWindows XP、Visual C++です。

質問者が選んだベストアンサー

  • ベストアンサー
  • R_Earl
  • ベストアンサー率55% (473/849)
回答No.2

我々が普段使っている数は、0, 1, 2, 3, 4, 5, 6, 7, 8, 9の十個の記号を組み合わせて表現します。 これは十進数と呼ばれています。 対してコンピューターは0, 1の二個の記号を組み合わせて数を表現します。 これは二進数と呼ばれています。 double型もfloat型も、二進数の形式で数を記録しています。 十進数だと、1/100(= 0.01)を小数で表現できますが、 1/3を小数で完璧に表現できません(0.333…と、終わりのない循環小数になる)。 十進数では分母が3の分数とは相性が悪いんです。 それと同じで、二進数は1/100(= 0.01)を小数で完璧に表現できません。 二進数では分母が100の分数とは相性が悪いからです。 十進数1/3が0.333…となったように、 二進数1/100も0.000000101000111…と終わりのない小数になります。 無限に続く数を保存することはできません。 そのため、double型やfloat型の変数に1/100を格納しようとすると、 変数には0.000000101000111…を途中で打ち切った数が格納されます。 『0.00000010100011』のような感じにです。 この打ち切り作業が誤差の原因です。 結局float、double型の変数を使っている以上、この手の誤差はどうしようもありません。

BearCave
質問者

お礼

理解できました。分かりやすい解説ありがとうございました。

その他の回答 (2)

  • titokani
  • ベストアンサー率19% (341/1726)
回答No.3

floatの有効桁は7桁程度なので、9桁も表示してはいけません。

  • asuncion
  • ベストアンサー率33% (2126/6286)
回答No.1

ないのではないでしょうか。 そもそも、double型の変数testの値が 「厳密に」0.01であるかどうかも怪しいと思います。 浮動小数点数を扱う際、その程度の誤差はありえますので、 トラブルとはいえないと思います。

BearCave
質問者

お礼

ありがとうございました。

関連するQ&A

  • double型からfloat型への型変換について

    double型で-999.999という数字をfloat型へキャストして 少数以下6桁をprintf文で表示すると、それぞれ以下の様になりました。 double -999.999000 float -999.999023 これは、単純にfloatの精度の問題なのでしょうか? また、計算機がどういうルールに基づいて計算をおこなっているということなのでしょうか? 教えてください。

  • doubleからintへのキャスト

    場合によって値が変わってしまいます。 これはいったいどういうことでしょうか?? 開発環境はWindows2000 VC++6.0 実行環境はWindows98です。 Windows2000で実行した場合は値は一緒なのですが Windows98の場合は値が変わってしまいます。 Windows98で下のプログラムを実行すると int test1; double test2; ・ ・ ・ test1 = (int)test2 char mes[1024]; printf(mes, "%lf, %d", test2, test1); test2は100.000000 そしてtest1が100となります。 しかし、プログラム実行中にプログラムメニューの[印刷]等、Windowsのメニューを使うと test2は100.000000なのですが test1が99になってしまいます。 これはいったいどういうことなのでしょうか。 値が減ることなんてありえるのでしょうか? よろしくお願いします。

  • doubleとfloatについて

    #include <stdio.h> int main() { float height,weight; printf("身長と体重を入力してください。\n"); scanf("%f",&height); scanf("%f",&weight); printf("身長は%fセンチ:体重は%fキロです。\n",height,weight); return 0; } 上記のようなプログラムを作って、身長には175.1体重には56.1という入力を行なって実行したところ、 身長は175.100006センチ:体重は56.099998キロです。 という結果が返ってきました。 heightとweightをdouble型で宣言したところ(もちろんscanf文の変換仕様は%lfにしています。)、結果は 身長は175.100000センチ:体重は56.100000キロです。 と私が、期待していたものが返ってきました。なぜfloat型だと期待通りの結果が返ってこないのでしょうか?ご教授お願い致します。

  • ArrayにDouble型の数字を格納

    環境はVisual Studio 2005 Standard Editionです. ArrayにDouble型の数字を格納しようしたら,以下のエラーが表示されました. 型 'System.Double' のオブジェクトを型 'System.Array' にキャストできません。 どのようにArrayを宣言すればよいのでしょうか.よろしくお願いします.

  • Float型の時の計算結果がおかしい

    ユーザー側で、Microsoft SQL Server2000を使用しています。 計算結果がおかしいので、仕事場で、SQL2008環境で互換モードでも、以下の現象が出てこまって おります。テストで、確認しました。 23.0 - 22.1 の計算結果を0.9と出したいのですが、  0.899999999999999 と結果が返ってきます。 どこが間違っているのでしょうか? SELECT [Field01] AS 'Field01' ,[Field02] AS 'Field02' ,[Field01]-[Field02] AS 'Field01-02' ,(CAST(23 AS FLOAT) - cast(22.1 AS FLOAT) ) AS 'test1' ,(CAST(23 AS REAL ) - cast(22.1 AS REAL ) ) AS 'test2' FROM [dbo].[Table01]

  • 文字列をfloatで読み込む(atoi,sscanf)。しかし、値がおかしい。

    お世話になっています。 C言語の質問です。 文字列をfloatで読み込もうとしているのですが、出力結果がおかしくて困っています。 文字列をatofで変換した場合、doubleでは上手く表示できるのですが、floatでは少数が上手く表示できません。 また、sscanfでも試したのですが、上手く表示できませんでした。 どうしても、doubleを使わずにfloatであらわしたいと考えています。 どうかこのプログラムの問題点のご指摘お願いします。 実行結果 53.196600 53.196602 53.196602 ソース #include<stdio.h> #include<stdlib.h> #include<string.h> main() { char str[100]="53.1966"; double b; float c,d; b = atof(str); printf("%f\n",b); c = (float)atof(str); printf("%f\n",c); sscanf(str,"%f",&d); printf("%f\n",d); } 開発環境 windowsXP cygwin

  • 関数プロトタイプ無しで、引数が float の場合

    またまた float がらみでつまずています。 以下のようなソース(2つのファイルに分割されています)を実行すると、 f = 2.000000 と表示されました。 test1.c で、func() のプロトタイプを書いてないのが諸悪の根源だとは思うのですが(警告もでています)プロトタイプの役割は、 ・引数の型の不整合がないようにする ・必要に応じて、仮引数と実引数の型変換を発生させる だと思います。 このソースでは(たまたまですが)引数の型もあっているので、正常に実行できそうな気がするのですが、なぜ、結果がおかしくなってしまうのでしょうか。 確かに、プロトタイプがないのは好ましくはないですが。 test1.c に、int func(float f); を追加したときには、確かに f = 0.010000 と表示されます。 また、f と func() の引数を double にしたときには、プロトタイプがなくても、正常に実行されます。 ----- test1.c ------------- int main() { float f = 0.01; func(f); return 0; } ----- test2.c ------------- #include <stdio.h> int func(float f) { printf("f = %f", f); return 0; } ----- ここまで ------------

  • c言語でint配列をdoubleに変換

    c言語でマイコンプログラムを作成しています. int型の配列をdoubleに変換するために以下のプログラムを記述し,テストしました. int a[4] = {0,0,1,8}; char s[4]; double d; char *temp; sprintf(s,"%d%d%d%d",a[0],a[1],a[2],a[3]); //文字列charをdoubleに変換 d = strtod(s,&temp); 望む結果は 18 ですが,なぜか上記結果は 1800 となりました. 試しに int a[4] = {1,2,3,4}; と,1234と表示されました. 上記より,出力値が左詰めのようになっています. 試しにVisual Studio 2013 C++で同様のプログラムを実行すると,所望の結果を得ることが出来ました. プログラムがおかしいのでしょうか?それともマイコンのコンパイラのバグでしょうか? お分かりになられる方がいらっしゃいましたら,ご教授宜しくお願い致します.

  • integer型、long型、double型

    vb6.0についてお聞きいたします。 こちらの問題は、visual studio 2005のvbでは生じません。 windows xp上で動かしているのですが、どうやら 何もしていないあるパラメータに32000ぐらいの数字よりも大きな 数字をいれるとエラーになってしまいます。 それも、integer型、long型、double型のすべての型で生じます。 そういうものなのでしょうか? HPをいろいろ見ましても、long型で20億ぐらいは 表現できるように書いてあるのですが。

  • 浮動小数点数の float型 での最少値について調べています。

    浮動小数点数の float型 での最少値について調べています。 「Visual C++ 2008 Express Edition」の「float.h」の中には、    #define FLT_MIN     1.175494351e-38F   /* min positive value */    #define FLT_MIN_EXP  (-125)           /* min binary exponent */ という記述があります。 float型で表現できる最少値が「1.175494351e-38F」なのだろうと思い、 下記のように 2^-125 を計算してみました。    printf("結果は、「%e」です。", pow((double)2, (double)(-125))); 実行結果は、    結果は、「2.350989e-038」です。 となり、「float.h」の「FLT_MIN」には一致しませんでした。 試しに、下記のようにしてみると( 2^-125 を 2^-126 に変えてみました )    printf("結果は、「%e」です。", pow((double)2, (double)(-126)));    結果は、「1.175494e-038」です。 となって「float.h」の「FLT_MIN」と「ほぼ一致」しているように見えます。 float型での最小値(FLT_MIN)を計算する際に「float.h」での「FLT_MIN_EXP」を使って    2^-125 とするのは間違っているのでしょうか?

専門家に質問してみよう