
C# 7.3において、float型の変数をdouble型にキャストした際、非常に小さな値の誤差が発生しています。
例:float : 29 → double : 29.0000009536743
なんとなく、誤差が発生しそうだな、という気はしますが、これの原因を正確に説明できなくて困っています。
より大きい値を扱える型へのキャストでは誤差は発生しないものと思っていたのですが…
よろしくお願いいたします。
追記
全く同じコードは掲載できないのでイメージでしかありませんが、以下のようなコードをUnity 2019.4.15fで実行した際に発生したものです。
C#
1int A = 29; 2int AMax = 45; 3float ARatio = A / (float)AMax; 4 5Debug.Log(AMax * ARatio) // 29 6Debug.Log(AMax * (double)ARatio) // 29.0000009536743
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。


退会済みユーザー
2022/05/17 13:44

退会済みユーザー
2022/05/17 14:02
2022/05/18 14:06

回答2件
0
ベストアンサー
float型で表現可能な29の次に大きい数値を求めて、double型に変換すれば、似たような結果にはなります。(参考URL)
c#
1using System; 2 3public class Test{ 4 public static void Main() { 5 float value = 29; 6 int bits = BitConverter.ToInt32(BitConverter.GetBytes(value), 0); 7 float nextValue = BitConverter.ToSingle(BitConverter.GetBytes(bits + 1), 0); 8 double d = nextValue; 9 Console.WriteLine(nextValue.ToString()); 10 Console.WriteLine(d.ToString()); 11 } 12}
結果
text
129 229.0000019073486
ただ、見ての通り、floatで表現可能な29の次に大きい数値をdoubleに変換しても29.0000019073486にしかならないので、29.0000009536743になるというのは何かの間違いではないでしょうか。
なお、ここで求めたfloat値とdouble値は、誤差なく完全に同じ数値です。
それなのにfloat値だけ29
と表示されてしまうのは、ToString()
の仕様が原因となります。
ToString()
に数値書式指定文字列を与えない場合のデフォルトは"G"
であり(参考URL)、"G"
に精度を指定しない場合のデフォルトはfloatの場合7桁なので、29
と表示されます。
追記への回答
Zuishinさんが別回答のコメントでおっしゃっている通り、AMax * (double)ARatio
の結果はdoubleで、AMax * ARatio
の結果はfloatです。(参考URL)
計算結果は正しくは29.0000009536743ですが、floatの精度では表現できない数値なので、丸められて29となります。
もしかして、全部floatで計算したほうが、途中でfloatをdoubleに変換して計算したときより、結果が正確に見えるのはなぜか、という質問でしょうか。
それは、最初にfloatで計算してしまってるので、途中でdoubleにしてもfloatでの有効桁までしか信用できないためです。
floatの有効桁は10進数で7桁+α、doubleの有効桁は15桁+αです。
最初にfloatで計算してしまっているので、その結果は7桁までしか信用できません。
その計算結果を後からdoubleにして15桁の有効桁で計算しても、15桁まで信用できるわけではなく、変わらず7桁までしか信用できません。
doubleは15桁まで信用できる前提で表示するので、29.0000009536743のように表示されて正しくないように見えますが、先頭7桁だけ見れば、29という正しい結果になっていることが分かると思います。
投稿2022/05/17 13:44
編集2022/05/17 21:04総合スコア2479
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
float は 4 バイト、double は 8 バイトの違いがある(浮動小数点を表すことができる精度に違いがある)のだから、違って当たり前ということで納得できませんか?
浮動小数点数値型 (C# リファレンス)
https://docs.microsoft.com/ja-jp/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types
投稿2022/05/17 11:31

退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2022/05/17 11:59
2022/05/17 12:10

退会済みユーザー
2022/05/17 12:14 編集

退会済みユーザー
2022/05/17 12:31 編集

退会済みユーザー
2022/05/17 13:22 編集

退会済みユーザー
2022/05/17 13:28 編集
2022/05/17 13:32
2022/05/17 13:38 編集

退会済みユーザー
2022/05/17 13:37

退会済みユーザー
2022/05/17 13:42
2022/05/17 13:44
2022/05/17 13:50

退会済みユーザー
2022/05/17 13:53

退会済みユーザー
2022/05/17 13:58
2022/05/17 14:25
2022/05/17 14:46
2022/05/17 15:16

退会済みユーザー
2022/05/17 15:29
2022/05/18 14:01

退会済みユーザー
2022/05/18 14:37
2022/05/19 14:31

退会済みユーザー
2022/05/19 23:15
2022/05/22 06:45

退会済みユーザー
2022/05/22 08:27 編集

あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。