こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

締切り済みの質問

float double の範囲

javaのサイト見てます
データ型にfloat doubleというのがあるのですが、
範囲が
float
3.40282347E+38
double
1.79769313486231570E+388
と記載されているのですが

これはどうゆう意味でしょうか?
小数点38桁388桁までという意味でしょうか?

投稿日時 - 2018-09-03 19:11:43

QNo.9533715

すぐに回答ほしいです

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(11)

ANo.11

>なんと衝撃の事実、doubleの誤差でループが正しく3回になっています(^_^;マジか?)。
>あくまでも誤差によるものなので、そんなものは当てにしてはいけません。

所詮doubleの誤差によるモノなので簡単に破綻します。
13回ループしたい場合(実際は14回ループしている)。

double start,stop,stride,step;
start = 0;
stop = 1;
step = 13;
stride = (stop-start)/step;
int loop = 0;
for(double l = start; l<stop; l+=stride){
loop++;
System.out.println("l="+l);
}
System.out.println("loop="+loop);

【実行結果】

l=0.0
l=0.07692307692307693
l=0.15384615384615385
l=0.23076923076923078
l=0.3076923076923077
l=0.38461538461538464
l=0.46153846153846156
l=0.5384615384615385
l=0.6153846153846154
l=0.6923076923076923
l=0.7692307692307692
l=0.846153846153846
l=0.9230769230769229
l=0.9999999999999998
loop=14

投稿日時 - 2018-09-04 10:31:44

ANo.10

>回答No.9 amanojaku1

古いソースをコピペしてしまいました。

double start,stop,stride,step;
start = 0;
stop = 1;
step = 3;
stride = (stop-start)/step;
int loop = 0;
for(double l = start; l<stop; l+=stride){
loop++;
System.out.println("l="+l);
}
System.out.println("loop="+loop);

【実行結果】

l=0.0
l=0.3333333333333333
l=0.6666666666666666
loop=3

投稿日時 - 2018-09-04 10:16:53

ANo.9

>回答No.8 amanojaku1

訂正ですm(_ _)m、forの条件「l<=stop」が間違っておりました。
なんと衝撃の事実、doubleの誤差でループが正しく3回になっています(^_^;マジか?)。
あくまでも誤差によるものなので、そんなものは当てにしてはいけません。

double start,stop,stride,step;
start = 0;
stop = 1;
step = 3;
stride = (stop-start)/step;
int loop = 0;
for(double l = start; l<=stop; l+=stride){
loop++;
System.out.println("l="+l);
}
System.out.println("loop="+loop);

【実行結果】

l=0.0
l=0.3333333333333333
l=0.6666666666666666
loop=3

投稿日時 - 2018-09-04 10:14:09

ANo.8

>回答No.7 amanojaku1

例えば3回ループしたかったとする。
下記はdoubleの誤差でループが4回になっている。
実際に どうしても浮動小数でループしたい場面はあるが、初め(プログラムの設計時)から整数が使えないか熟考してみた方が良い(できるだけ整数にできないか熟考することをオススメします)。

double start,stop,stride,step;
start = 0d;
stop = 1d;
step = 3d;
stride = (stop-start)/step;
int loop = 0;
for(double l = start; l<=stop; l+=stride){
loop++;
}
System.out.println("loop="+loop);

【実行結果】

loop=4

投稿日時 - 2018-09-04 09:53:10

ANo.7

>回答No.6 amanojaku1

floatの誤差は酷過ぎるが、doubleでも誤差は出る。
演算の回数が増えるごとに どんどん誤差は大きくなるので、シビアな計算が必要な場合は誤差が最小になるように工夫が必要になる。
内部的に2進で演算しているので(浮動小数点表示の小数部と言う意味ではなく)実際の数値の小数部でも誤差は出る。
例えば消費税の計算で端数の処理(切捨て、切上げ、四捨五入など)があるが、実際の会計処理で切捨てで誤差が出た場合、法律に抵触する事になる(これは「切上げ、四捨五入」で誤差が出ないと言う事ではない)。
内部的に2進で演算している場合(float、double)は要注意。

投稿日時 - 2018-09-04 09:13:00

ANo.6

>回答No.5 amanojaku1
>回答No.2 amanojaku1

例えば「String.format(~)」で浮動小数点表示の小数部を20桁表示させてみると。

(例1).System.out.println(String.format("%1.20e", 2042f/125f*375f*10000000000000000000f));

【実行結果】

6.12599977585250600000e+22

↑(誤差があると言う前提で)8桁目から おかしな数字になっている、また最後の方にゼロが続いているが、内部的に表示上の数字を切り捨てているだけで実際はゼロではない。



(例2).System.out.println(String.format("%1.20e", 2042d/125d*375d*10000000000000000000d));

【実行結果】

6.12599999999999900000e+22

↑(誤差があると言う前提で)16桁目から数字がゼロになっているが、内部的に表示上の数字を切り捨てているだけで実際はゼロではない。



(例3).System.out.println(String.format("%1.20e", 2042d/125d*375d*10000000000000000000d-6.12500000e+22));

【実行結果】※(例2)は16桁目から数字がゼロになっているが、16桁目からも数字が存在すると言う証明。

9.99999999998479600000e+18

↑(例2)から「6.12500000e+22」を引いている、(誤差があると言う前提で)結果として12桁目から おかしな数字になっている、また最後の方にゼロが続いているが、内部的に表示上の数字を切り捨てているだけで実際はゼロではない。

投稿日時 - 2018-09-04 08:23:06

ANo.5

>回答No.2 amanojaku1

内部的に2進で演算しているので演算誤差がでます。

System.out.println(2042d/125d*375d);
System.out.println(2042d/666d*375d*777d);

【実行結果】

6125.999999999999
893375.0000000001

投稿日時 - 2018-09-04 00:00:23

ANo.4

>float
>3.40282347E+38
>double
>1.79769313486231570E+388
>と記載されているのですが
違うでしょう。
概数ですが次のようになります。
3.40282347E+38 → 3.4E +/- 38 → 3.4E-38~3.4E38
1.79769313486231570E+388 → 1.7E +/- 308 → 1.7E-308~1.7E308

>小数点38桁388桁までという意味でしょうか?
0を挟んで+側と-側の桁数がfloatは38桁でdoubleが308桁まで扱える範囲です。
有効な数値は夫々7桁と15桁のようです。
扱える数値と有効桁数で矛盾を感じるかも知れませんがソロバンで計算するのと計算尺で計算することを比較すれば理解できると思います。

投稿日時 - 2018-09-03 23:43:08

ANo.3

388じゃなくて308ですね。

floatで表せる最大値が 3.40282347 x 10の38乗、
doubleで表せる最大値が 1.7976931348623157 x 10の308乗 ということです。
有効数値は、floatが7桁強、doubleが16桁強です。それ以降の桁は誤差です。

数字が半端なのは、2進数データを10進数換算したからです。

投稿日時 - 2018-09-03 21:35:46

ANo.2

>小数点38桁388桁までという意味でしょうか?

違います。



System.out.println(Math.sqrt(2f));
System.out.println(Math.sqrt(200000000000000000000f));

【実行結果】

1.4142135623730951
1.4142135765441353E10

floatの有効桁数:約6~7桁
※上記の実行結果は9桁目から数字が一致してない。



System.out.println(Math.sqrt(2d));
System.out.println(Math.sqrt(200000000000000000000d));

【実行結果】

1.4142135623730951
1.4142135623730951E10

doubleの有効桁数:15桁
※上記の実行結果は17桁目まで数字が一致している。

投稿日時 - 2018-09-03 21:25:57

ANo.1

3.40282347E+38=3.40282347*10^(+38)
1.79769313486231570E+388=1.79769313486231570*10^(+388)
ということです。Eという文字とその後にある数値で10の累乗を掛けるという意味になります。指数表示と言います。

1.2345E-2=0.012345
1.2345E-1=0.12345
1.2345E0=1.2345
1.2345E1=12.345
1.2345E2=123.45
1.2345E3=1234.5

投稿日時 - 2018-09-03 19:46:55

あなたにオススメの質問