
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
ピッタリ合っている
宜しくお願いします。
No.4ベストアンサー
- 回答日時:
> 誤差が拡大するのは分かるのですが、次の部分の誤差が大き過ぎると思います。
FLT_DIGを調べれば分かることですが、単精度浮動小数点数の精度は10進法で6桁程度しかありません。
回答有り難う御座います。
HEWのマニュアルに浮動小数点数の仕様が書いて有りました。
それから最大値を計算すると、次のようになりました。
16777215 * 2^104 =
3.402823466 3852885981170418348452e+38
すると、次の値が妥当のようです。
#define FLT_MAX 3.402823466e+38F
更に最大値の次の値は下のようになりました。
16777215 * 2^104 =
3.402823466 3852885981170418348452e+38 最大値
16777214 * 2^104 =
3.402823263 5611925616003375953727e+38 最大値の次の値
3.402823466 と 3.402823263 の差が大きいのが分かります。
これで、次の疑問も解けました。
----------------------------
FLT_MIN に比べ有効桁数が多いのが気になる。
同じ有効桁数で区切っても ...567 と ...466 とでは誤差が大きい。
FLT_MAX 3.402823567 7973364e+38f
Max= 3.402823466 385288600E+38
FLT_MIN 1.175494351e-38F
----------------------------
まだ次のように、実験結果が今までの計算と合っているのに、HEWの
ヘッダの値が他と違うと言う疑問が残りますが、大体の疑問が解けました。
みなさん、有り難う御座いました。
#define FLT_MAX 3.402823567 7973364e+38f HEW
実験結果 Max= 3.402823466 385288600E+38
No.5
- 回答日時:
>誤差については分かるのですが、次の部分の誤差が大き過ぎると思っています。
単精度の仮数部は、省かれた1ビットを含め、25ビットしかありません。
つまり「2の25乗」の精度しかありません。
「2の25乗」は「33554432」ですから「10進数で7桁」だけが有効です(2進数の0~33554432の範囲で表わせる10進数は0~9999999までの7桁)
「7桁だけ有効」と言うことは「整数部1桁+小数部6桁」しか信じられないので、小数部6桁で切ると
#define FLT_MAX 3.402823 5677973364e+38f HEW
実験結果 Max= 3.402823 466385288600E+38
となり、切った小数7桁以下は「無効なので無視しなければならない桁」です。
小数7桁以下を無視すると、どちらも「同じ数値」になります。
言い換えると「小数点以下7桁目が4でも5でも、2進化して単精度の浮動小数点数にコンバートすると、同一のバイナリ値が出来あがる」って事です(小数点以下7桁目が3とか2とかだと、微妙に小さい値になってしまうでしょうから駄目です。また、6とか7とかだとオーバーフローの危険があるので駄目です)
試しに
float f1;
float f2;
f1=3.4028235677973364e+38f;
f2=3.402823466385288600E+38f;
sprintf(str,"%s\r\n",f1 == f2 ? "EQU" : "Not EQU");
Put_str(str);
と言うプログラムを書いてみましょう。
実行すると
EQU
になる筈です。
この結果により「10進表記が異なっていても、異なるのは有効桁の外(つまり無効桁)なので、内部のバイナリ値が一緒になり、f1とf2が等しくなる」のが判るでしょう。
回答有り難う御座います。回答を書くのに時間が掛かったでしょう。
有効桁数が意外に少ないと言うのは、回答番号4のお礼に有るように分かりました。
みなさんが良く回答してくれるので更に調べ、次の事が分かりました。
(2^24 - 1) * 2^104 =
3.402823466 3852885981170418348452e+38
3.402823466E+38F 【比較用】あるメーカのFLT_MAX
(2^25 - 1) * 2^103 =
3.4028235677973366 163753939545814e+38
3.4028235677973364e+38f 【比較用】ルネサスと秋月のFLT_MAX
(2^24 - 1)は、111111... と1が23個並んだ2進数を10進数に変換した物。1111 を求めるのに (10000 - 1)として計算。
仮数22ビット+上位の固定1 で合計23ビットの1。
ルネサスの FLT_MAX に近い物が得られました。これで納得と行きたい所ですが、まだ最後の所が366と364で、2の違いが有りますね。
四捨五入でも納得出来ないし、何だろう。パソコン・アクセサリの電卓のバグだったりして。電卓にも今回と同じような問題が有り、表示されていても無効な数字なのかも知れません。
次のように変更して計算してみましたが、同じ結果でした。少しは変化すると思ったのですが、全く同じと言うのも意外です。
方法1 2^103 * (2^25 - 1)
方法2 2^128 - 2^103
ここまで分かったから、もういいかなと思っています。
No.3
- 回答日時:
定義は合ってますが、表示方法が間違っています。
sprintfなどの「printf系関数」は「単精度実数を引数に与えると、倍精度実数に変換する」のです。
この変換の際に、4バイトから8バイトに拡張する為、大きく誤差が出ます。
しかも、10進数表記(「0.123E+30」など、人間が理解出来る表記)にする際に、丸め誤差など、更に誤差が蓄積します。
簡単に言うと「貴方が目で見ている表示は、いろいろなキャストや変換が行われた後の結果で、元の数値とは似ても似つかないもの」なのです。
少なくとも「float⇒double」のキャストによって「全然違う値」になります。
実験するのであれば「FLT_MAX、FLT_MINを、floatの変数に代入し、変数の中身を16進ダンプする」のが正解です。
そして、16進ダンプした結果を見て、バイナリで「指数部が最大値になってて、仮数部が全部1で埋まってる」のを確認しましょう。
因みに「3.4028235677973364e+38fと書かれたソース上の文字列を、floatのバイナリ値に変換する際」に「既に誤差を含んでいる」のをお忘れ無く。
何故なら「10進数での有限小数が、2進数では無限小数になる」からです(「0.1」は「10進数では有限小数」ですが「2進数では循環小数」になり、0.1を2進数で正確に表現する事は不可能なのです)
つまり「3.4028235677973364e+38fと言う10進数の数値は、2進数では正確に表現不可能」なのです。
いつも回答有り難う御座います。
誤差については分かるのですが、次の部分の誤差が大き過ぎると思っています。
有効桁数が違うから、下半分の桁はゴミだと言うのは分かります。
-------------------------
FLT_MIN に比べ有効桁数が多いのが気になる。
同じ有効桁数で区切っても ...567 と ...466 とでは誤差が大きい。
FLT_MAX 3.402823567 7973364e+38f
Max= 3.402823466 385288600E+38
FLT_MIN 1.175494351e-38F
No.2
- 回答日時:
H8のHEWは長い間触っていないので詳しいことは忘れましたが、SHのものはfloatとdoubleを常に同じ(両方単精度または倍制度)にするオプションがあったように思います。
それと同じか、同じなくてもヘッダを使い回している可能性がありますので、有効桁数以上を記述していること自体はそれほど問題ありません。
ただ、floatが単精度で、doubleが倍精度の場合、FLT_MAXはどうしても単精度の有効桁数までしか表現できません。そして、可変個数引数としてprintfに渡す際にdoubleに変換されますので、その辺りで誤差が拡大することになります。
いつも回答ありがとう御座います。
>floatとdoubleを常に同じ(両方単精度または倍制度)にするオプションがあったように思います。
調べると、倍精度を単精度にするオプションが有りました。
誤差が拡大するのは分かるのですが、次の部分の誤差が大き過ぎると思います。
-----------------------------
同じ有効桁数で区切っても ...567 と ...466 とでは誤差が大きい。
FLT_MAX 3.402823567 7973364e+38f
Max= 3.402823466 385288600E+38
No.1
- 回答日時:
実際のfloatで表現できる最大値以上を定義しているからでしょう
そのfloat.hのFLT_MAXは明らかにおかしいですね
誰かが書き換えたんじゃないですか
ちなみにVisualC++では
#define FLT_MAX 3.402823466e+38F
でした
早速の回答有り難う御座います。
>そのfloat.hのFLT_MAXは明らかにおかしいですね
誰かが書き換えたんじゃないですか
それは有りません。ルネサスからインストールして、私個人で使っていますから。
調べてみると、下記のように幾つか有りました。
(2)の方法は(1)よりも1桁少なくなっています。これは四捨五入のためじゃないかと思っています。
すなわち(1)の方式だと 1/3 * 3 としたときに 0.9999999 と表示され、(2)の方式だと 1.000000
と表示されるんじゃないかと思っています。(少数以下の桁数は適当に書きました。)
秋月電商のCコンパイラ
#define FLT_MAX 3.4028235677973364e+38f
#define FLT_MIN 7.0064923216240862e-46f
ルネサスHEW
#define FLT_MAX 3.4028235677973364e+38f
#define FLT_MIN 1.175494351e-38F
FLT_MAX 3.402823466E+38F(1)
FLT_MIN 1.175494351E-38F
FLT_MAX 3.40282347e+38f(2)有効桁数が1桁少ない
FLT_MIN 1.17549435e-38f
#define FLT_MAX 3.40282347e+38F
#define FLT_MIN 1.17549435e-38F
#define FLT_MAX 3.402823466e+38
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# プログラミングを教えて欲しいです。 配列aは、int a[9]={7,6,12,8,3,5,10,9 4 2022/12/19 23:27
- JavaScript ソースコードのいじる場所が分かりません。 1 2022/12/23 02:06
- C言語・C++・C# C言語のエラーについて 2 2022/07/11 13:56
- オープンソース cssで中央寄せ 1 2023/05/19 06:25
- Visual Basic(VBA) 3つのプロシージャをまとめたら実行時エラー発生で対応不能 6 2022/05/17 01:47
- C言語・C++・C# C言語:数値の桁数指定についての質問です。 8 2022/05/26 23:53
- 自転車修理・メンテナンス マウンテンバイクのタイヤについてです。タイヤを細いスリックタイヤに変えたいのですが、スポークも変えな 2 2022/04/12 18:19
- C言語・C++・C# C言語について コマンドラインで >変数 12.00 (char型) と、小数点付きの値を共用体に渡 1 2022/04/22 16:56
- 車検・修理・メンテナンス 冷却水のリザーブタンクが全く見えない位置にあるのでラジエターキャップの縁スレスレまで冷却水を補充して 4 2023/02/07 22:03
- 数学 X_1,…X,nを独立で同じ確率分布に従う確率変数列とする。 Xmin=min{X_1,…,Xn}, 5 2023/01/13 22:00
関連するカテゴリからQ&Aを探す
今、見られている記事はコレ!
-
弁護士が語る「合法と違法を分けるオンラインカジノのシンプルな線引き」
「お金を賭けたら違法です」ーーこう答えたのは富士見坂法律事務所の井上義之弁護士。オンラインカジノが違法となるかどうかの基準は、このように非常にシンプルである。しかし2025年にはいって、違法賭博事件が相次...
-
釣りと密漁の違いは?知らなかったでは済まされない?事前にできることは?
知らなかったでは済まされないのが法律の世界であるが、全てを知ってから何かをするには少々手間がかかるし、最悪始めることすらできずに終わってしまうこともあり得る。教えてgooでも「釣りと密漁の境目はどこです...
-
カスハラとクレームの違いは?カスハラの法的責任は?企業がとるべき対応は?
東京都が、客からの迷惑行為などを称した「カスタマーハラスメント」、いわゆる「カスハラ」の防止を目的とした条例を、全国で初めて成立させた。条例に罰則はなく、2025年4月1日から施行される。 この動きは自治体...
-
なぜ批判コメントをするの?その心理と向き合い方をカウンセラーにきいた!
今や生活に必要不可欠となったインターネット。手軽に情報を得られるだけでなく、ネットを介したコミュニケーションも一般的となった。それと同時に顕在化しているのが、他者に対する辛らつな意見だ。ネットニュース...
-
大麻の使用罪がなかった理由や法改正での変更点、他国との違いを弁護士が解説
ドイツで2024年4月に大麻が合法化され、その2ヶ月後にサッカーEURO2024が行われた。その際、ドイツ警察は大会運営における治安維持の一つの方針として「アルコールを飲んでいるグループと、大麻を吸っているグループ...
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
有効数字について 以前質問をし...
-
VS2010でのint float数値について
-
乱数について
-
4096bitを95種類で表現すると何...
-
計算が合わない
-
2進数 → 10進数変換 模範解答と...
-
O(n log n)について2
-
2進数の足し算(C言語)
-
VisualBasic6.0 SP5 のおもしろ...
-
0.1の10000回の累積
-
C言語の実数型の足し算
-
if文がうまく回りません。
-
VBAでの割り算の余りの求め方
-
CRCの計算方法について
-
16進数とかわからないです
-
定数の定義方法 #define
-
floatの有効桁数
-
MATLABでの行列の全要素の和
-
ExcelでPC(パソコン)によって...
-
Excelで小数点以下の値が正常に...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
有効数字について 以前質問をし...
-
三菱シーケンサ(Aシリーズ)で...
-
ExcelでPC(パソコン)によって...
-
c languageで 簡単な質問があ...
-
ExcelのINT関数の計算結果がお...
-
VB.net Double と...
-
VBAでミリ秒まで出力する方法
-
16進数 加算 減算 C言語
-
EXCELの関数"STDEV(標準偏差)"...
-
floatの有効桁数
-
除算を使わずに10で割りたい。
-
計算の丸め誤差の解消について
-
VB6.0での小数点の扱いについて
-
コンピューターは指数関数をど...
-
2038年問題 日付算出
-
時刻の比較
-
2進数、16進数、10進数のことを...
-
浮動小数演算は実行環境の変化...
-
2進数の足し算(C言語)
おすすめ情報