• ベストアンサー

doubleで表現できる最も小さな値

たとえば double num = 1.0; このnumよりも大きなdoubleで表現できる最も小さな値を生成したいと考えています。 FLT_MINを単純に足してもnum==num+FLT_MINとなってしまいます。 num != num2となるような最小値の作りかたを教えて下さい

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

  • ベストアンサー
回答No.7

No.3です。 回答の中に、実はヒントがあったのですが……。 さて、IEEE 754の形で表すとき、仮数部は2進数で52桁(+先頭に 1 を仮定)です。 だから、1.0 に影響を与える絶対値の最も小さい数値は、2進数で52桁目にある、2^(-52) です。 言い換えると、 1.(0 が 52個)に影響を与えるためには、0.(0 が 51個)1 が最小になります。 これが、2進数で、 1.1111111 を超えて 10.00000 (実際には指数部がひとつかわるけど)つまり、2.0 になるまで続きます。 ということで、(以下、表記は 10進数) 1.0 以上 2.0 未満 刻みは DBL_EPSILON 2.0 以上 4.0 未満 刻みは DBL_EPSILON * 2 4.0 以上 8.0 未満 刻みは DBL_EPSILON * 4 となります。 一般化すれば、 2^n 以上 2^(n + 1) 未満 で、刻みは DBL_EPSILON * 2 ^ n です。 (n < 0 でも同じ)

その他の回答 (7)

  • qwertfk
  • ベストアンサー率67% (55/81)
回答No.8

浮動小数の仕様を考えると、正の場合は double get_next(double d) {  double next_d = d;  unsigned long long& l = (unsigned long long&)next_d;  if( l & 0xfffffffffffff == 0xfffffffffffff )  {   l = l - 0xfffffffffffff;   l += 0x10000000000000;  }  else  {   l += 1;  }  return next_d; } でいけるんじゃないかと思います。 基本的には仮数部*2^nという構造になっており、仮数部は1.0~1.9999...なので 二つの数を比較するときに、まず指数部が一致していなければ指数部が大きいほうが大きい値、 そうでなければ仮数部の大きいほうが大きい値、となっているはずなので。

回答No.6

> ある数値の次の数値 C99のnextafter関数

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

>このnum(直前に出てきた1.0のことですよね?)よりも大きなdoubleで表現できる最も小さな値を生成したい この文の意味がどうしてもわかりません。 どなたか解説をお願いできないでしょうか。

northbig
質問者

補足

分かりにくい質問になってしまい申し訳ありません。 どうやら先に回答いただいたDBL_EPSILONで問題は解決しそうですが 本来の意図とは異なっています。 本来の質問のイメージは double型は8バイトなので(2^8)^8個(パターン)の数が表現できます。 実際はNaNなどがあるのでそれよりも少なくなると思いますが。 この数列を昇順にソートしたときの ある数値の次の数値が知りたいのです。 doubleの刻み幅は常にDBL_EPSILONではないようなので厄介なのです もう少し回答を募ってみようと思います。

  • samtomsan
  • ベストアンサー率55% (1060/1897)
回答No.4

ANo.2です。 忘れていました。 FLT_MINはfloatですから、doubleの場合はDBL_MINですね。 http://simd.jugem.jp/?eid=18 下記も参考になると思います。 http://www.cc.kyoto-su.ac.jp/~yamada/programming/float.html

回答No.3

すでに回答がありますが、このような数値は、DBL_EPSILON と定義されています。 手元のコンパイラ(のヘッダファイル)を調べると、具体的には、2.2204460492503131E-16 という数値のようです。 さて、この数値はなんでしょうか? また、なぜ、num == num + DBL_MIN (double なら、FLT_MIN はそもそもおかしいでしょう)なのかという点です。 まず、現在多く使われている浮動小数点は、IEEE 754形式と呼ばれるものです。 これで、double を表すと、 符号 1 + 小数点以下52桁(ただし2進数で)*2 ^(指数) となります。 ※実際には、(指数)は、以下の説明とは具体的な数値はちょっと違います。 ※あと、ここで使っている ^ はべき乗の意味とします(この説明では、ビット演算子ではありません) さて、実は、DBL_EPSILON (2.2204460492503131E-16) は、2倍して、2倍して……と、52回繰り返すと、ぴったり1になる数値です。 言い換えると、2^(-52) に相当する数値です。 1.0 = (1 + 小数点以下は、0 )* 2^0 であることを考えると、IEEE 754 で表すと 1.0 = (1 + 小数点以下である52個の0)* 2 ^ 0 になります。 (ただし表記は2進数) これに何かを足して、1.0 じゃないものにしようと思えば、小数点以下にならんだ52個の0を変化させなければいけません。 つまり、0.(51個の0)1 (ただし表記は2進数)が最小の数値です。 10進数では 1.0/10 = 0.1, 0.1/10 = 0.01, 0.01/10 = 0.001 と、10で割るごとに桁がひとつ下がってゆきます。 同じように2進数では 1.0/2 = 0.1, 0.1/2 = 0.01, 0.01/2 = 0.001 と2で割るごとに桁がひとつ下がってゆきます。(ただし表記は2進数) つまり、2進数表示で、 0.(51個の0)1 という数値は、2で割ることを52回繰り返した数字になります。 これが、DBL_EPSILON = 2.2204460492503131E-16 = 2^(-52) という意味です。 一方で、DBL_MIN (2.2250738585072014E-308)は、1.0 からみると2進数表記で小数点以下 1024桁の数値になります。 数値を表すのに、たかだか 2進52桁しかないのに、1024桁も小さい数値を足しても、結果は変わらないということになります。

  • samtomsan
  • ベストアンサー率55% (1060/1897)
回答No.2

パソコンの場合の数値表現はIEEE754ですから、下記のIEEE754倍精度の場合の説明を見れば判るかと思います。 http://d.hatena.ne.jp/lemniscus/20090816/1250441897

回答No.1

URL参照。

参考URL:
http://ja.wikipedia.org/wiki/%E8%A8%88%E7%AE%97%E6%A9%9F%E3%82%A4%E3%83%97%E3%82%B7%E3%83%AD%E3%83%B3

関連するQ&A

  • 浮動小数点数の 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 とするのは間違っているのでしょうか?

  • double型で収まりきれない小数の値を求めたい。

    下記のようなプログラムを作っています。 int num = 1000; double d1 = 12345.6; double d2 = 0.0: for(int i=0;i<num;i++){   d2 += Math.pow(d1,(double)i); } d2の値を求めたいのですが、これをこのまま実行すると、得られる数値が大きすぎてd2の値がInfinityになってしまいます。 小数を格納できる最大の型はdouble型ですよね? それに収まりきらないということは、私の求めたい数値はJavaでは求めることが出来ないのでしょうか? それとも何かInfinityになってしまうのを回避する手段はあるのでしょうか? d2で得られた値はそのまま他の計算式で利用するのでどうしてもすべて小数値でなくてはならないのです。 どなたかお知恵をお貸しください。 よろしくお願いします!!

    • ベストアンサー
    • Java
  • float.h のテスト結果がおかしい

     float.h  をテストするため、次のようなプログラムを作りました。  float.h に書かれている値が書き出されると思ったのですが、少し値が違います。  FLT_MAX と DBL_MAX の値が違っています。本当にこのヘッダファイルを読んでいるかと思い、 #define FLT_MAX 3.4e+3f    と変更すれば、 Max= 3.400000000000000000E+03 と出てきます。  一致しない原因は何でしょう。  コンパイラはルネサスのHEWで、CPUはH8/3052です。 *** float.h *** #define FLT_MAX 3.4028235677973364e+38f #define FLT_MIN 1.175494351e-38F #define DBL_MAX 1.7976931348623158e+308 #define DBL_MIN 2.2250738585072014e-308 *** プログラム *** sprintf(str," float :%ldBytes Max= %.18E Min= %.18E\r\n", sizeof(float), FLT_MAX, FLT_MIN) ; Put_str(str) ; sprintf(str," double:%ldBytes Max= %.18E Min= %.18E\r\n", sizeof(double), DBL_MAX, DBL_MIN) ; Put_str(str) ; *** 結果 *** float :4Bytes Max= 3.402823466385288600E+38         Min= 1.175494350822287500E-38 double:8Bytes Max= 1.797693134862315700E+308          Min= 2.225073858507201400E-308 *** まとめて整理 ***  元の原稿は比較し易いように縦に数字が並ぶように書いているのですが、 ここに書き込むとずれてしまいます。 #define FLT_MAX 3.4028235677973364e+38f         Max= 3.402823466385288600E+38  FLT_MIN に比べ有効桁数が多いのが気になる。  同じ有効桁数で区切っても ...567 と ...466 とでは誤差が大きい。    FLT_MAX 3.402823567 7973364e+38f       Max= 3.402823466 385288600E+38     FLT_MIN 1.175494351e-38F #define FLT_MIN 1.175494351e-38F         Min= 1.175494350822287500E-38  四捨五入なら分かる。 #define DBL_MAX 1.7976931348623158e+308         Max= 1.797693134862315700E+308  最後が8と7で違う。しかし、DBL_MAX は8バイトで表せる値に対して四捨五入したために7が8になったと考えれば納得出来る。 #define DBL_MIN 2.2250738585072014e-308         Min= 2.225073858507201400E-308  ピッタリ合っている  宜しくお願いします。

  • 最大値と最小値を表示したいのですが・・・

    double numに入っている数字から最大値と最小値を求めたいのですが、このままだと両方とも1.000になってしまうんです・・・ どうやったらちゃんと最大値と最小値が表示されるのでしょうか?? 初心者なものでスイマセンが教えてください!! #include<stdio.h> int main(void) { int i,j; double num[]={4.5,3.1,7.0,9.2,1.0,5.7,9.3,2.3,0.3,1.0}; double max,min; for(i=0; i<10; i++) { for(j=0; j<10; j++) { if(num[i]>num[j]) max=num[i]; } } for(i=0; i<10; i++) { for(j=0; j<10; j++) { if(num[i]<num[j]) min=num[i]; } } printf("最大値は%fです。",max); printf("最小値は%fです。",min); return 0; }

  • 【機械図面】 最大値・最小値はどう表現するの?

    タイトルの通りです。 例えば寸法線として、50mmを「最小値」としたい場合、 下記のような表現は可能なのでしょうか?(どれが良い表現でしょうか?) (1)”50 Min.”もしくは”50 最小” (2)”Min.50” もしくは”最小 50” (3)公差で表現する(例えば+10/-0) (4)その他 見やすさの観点から、できれば(3)は避けたいと考えています。 手元にJIS等のハンドブックがないため、お尋ねします。 アホな質問かと思いますが、宜しくお願いします。

  • C言語の配列について

    main() { int i; double min=100; double A[4]={50,2,1,3}; for(i=0; i<4; i++) {if(A[i]< min) min=A[i];} printf("%lf",min); } このようなプログラムを組んで配列Aの要素の最小値を求めています。 上記のプログラムで最小値はもとまるのですが、最小値を取るときの番地??(A[?]=1の?の値のことです。上記プログラムではA[2]=1なので2です。)をとりだしたいのですが、良い方法はないでしょうか?? アドバイスお願いします。

  • javaプログラムについて

    コマンドライン引数から複数の値を受け取り、それらの最大と最小を表示する、というプログラムなのですが。 class Maxmin{   public static void main (String[] args) {    int max=Integer.MIN_VALUE;    int min=Integer.MAX_VALUE;    for (int i=0; i<args.length; i++){     int num= Integer.parseInt(args[i]);     if(num>max)     max=num;     if(num<min)     min=num;    }    System.out.println("最大値は" + max + "です。");    System.out.println("最小値は" + min + "です。");  } } このプログラムでも問題なく表示されるのですが、MIN_VALUEとMAX_VALUEを使用せずに表示する事、と指摘を受けました。自分の中でぱっと思いついたのがこれだったのですが、他にはどのような方法があるのでしょうか?

    • ベストアンサー
    • Java
  • グループごとの一番小さい値を取り出したい

    データベースに列A、Bがあり、その中は A b 1 1 1 2 1 3 1 4 2 2 2 3 2 5 を入力されていて、以下のようにAのグループの中の値で最小値を取得したいのです。 A B 1 1 2 2 MIN関数を使用すると、テーブル全ての最小値を取得してしまうので、上手くいきません。何かいい方法があるでしょうか?

  • 「"」(ダブルクォーテーション)で囲まれた「,」をキャンセルしてcsvの値を抽出するには

    111,"あいうえお",,"さしす,せそ" のテキストファイルを value[0] = 111 value[1] = あいうえお value[2] = value[3] = さしす,せそ いう形に配列に入れたいと思っています。見てもらえばわかると思いますが、数字には「"」(ダブルクォーテーション)が付かなくて、「"」の中に入っている「,」(カンマ)は区切り記号とはみなされず値として取り込んでいます。 splitの正規表現など使えないか苦悩しています。いまだ解決方法見つけられず。 テキストファイルの「"」(ダブルクォーテーション)有り/無しや順番などは都度変更されます。 カンマ区切りで、「"」(ダブルクォーテーション)で囲まれた部分は外して値を取り出すにはどうしたらいいのでしょう? ご存知の方、ご教授ください。

    • ベストアンサー
    • PHP
  • EPSILONとMIN_VALUEの違い

    Number.EPSILON とNumber.MIN_VALUEは、何が違うのでしょうか。 以下のURLの「同等なことをテストする」では、EPSILONと数値の差を比較し、浮動小数点の計算誤差を確認していますが、EPSILONをMIN_VALUEにするとequalはfalseになります。 https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON MIN_VALUEとEPCILONとで値が違うので、結果も異なってくるのだとは思うのですが、そもそもどのように使い分ければよいのかが理解できませんでした。 MIN_VALUEは「JavaScriptで表せる0に最も近い最小の値」、EPCILONは、「1より大きい最小の値の差」で、結局、どちらも表現できる最小の値に見えるのですが、何が違うのでしょうか。

専門家に質問してみよう