回答編集履歴

4

有効桁の説明追加

2022/05/17 21:04

投稿

actorbug
actorbug

スコア2226

test CHANGED
@@ -33,3 +33,13 @@
33
33
  Zuishinさんが別回答のコメントでおっしゃっている通り、`AMax * (double)ARatio`の結果はdoubleで、`AMax * ARatio`の結果はfloatです。([参考URL](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#11473-binary-numeric-promotions))
34
34
 
35
35
  計算結果は正しくは29.0000009536743ですが、floatの精度では表現できない数値なので、丸められて29となります。
36
+
37
+ ---
38
+
39
+ もしかして、全部floatで計算したほうが、途中でfloatをdoubleに変換して計算したときより、結果が正確に見えるのはなぜか、という質問でしょうか。
40
+ それは、最初にfloatで計算してしまってるので、途中でdoubleにしてもfloatでの有効桁までしか信用できないためです。
41
+
42
+ floatの有効桁は10進数で7桁+α、doubleの有効桁は15桁+αです。
43
+ 最初にfloatで計算してしまっているので、その結果は7桁までしか信用できません。
44
+ その計算結果を後からdoubleにして15桁の有効桁で計算しても、15桁まで信用できるわけではなく、変わらず7桁までしか信用できません。
45
+ doubleは15桁まで信用できる前提で表示するので、29.0000009536743のように表示されて正しくないように見えますが、先頭7桁だけ見れば、29という正しい結果になっていることが分かると思います。

3

また質問が変わっていたので、そちらに合わせて修正

2022/05/17 14:54

投稿

actorbug
actorbug

スコア2226

test CHANGED
@@ -1,13 +1,3 @@
1
- Zuishinさんが別回答のコメントでおっしゃっている通り、`AMax * (double)ARatio`の結果はdoubleで、`AMax * ARatio`の結果はfloatです。([参考URL](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#11473-binary-numeric-promotions))
2
-
3
- 計算結果は正しくは29.0000009536743ですが、floatの精度では表現できない数値なので、丸められて29となります。
4
-
5
- ---
6
- 以下は、修正前の質問に対する回答になります。
7
-
8
-
9
-
10
-
11
1
  float型で表現可能な29の次に大きい数値を求めて、double型に変換すれば、似たような結果にはなります。([参考URL](https://stackoverflow.com/questions/9485943/calculate-the-unit-in-the-last-place-ulp-for-doubles))
12
2
  ```c#
13
3
  using System;
@@ -36,3 +26,10 @@
36
26
  それなのにfloat値だけ`29`と表示されてしまうのは、`ToString()`の仕様が原因となります。
37
27
 
38
28
  `ToString()`に数値書式指定文字列を与えない場合のデフォルトは`"G"`であり([参考URL](https://docs.microsoft.com/ja-jp/dotnet/api/system.single.tostring?view=net-6.0))、`"G"`に精度を指定しない場合のデフォルトは[floatの場合7桁](https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/standard-numeric-format-strings#general-format-specifier-g)なので、`29`と表示されます。
29
+
30
+ ---
31
+ 追記への回答
32
+
33
+ Zuishinさんが別回答のコメントでおっしゃっている通り、`AMax * (double)ARatio`の結果はdoubleで、`AMax * ARatio`の結果はfloatです。([参考URL](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#11473-binary-numeric-promotions))
34
+
35
+ 計算結果は正しくは29.0000009536743ですが、floatの精度では表現できない数値なので、丸められて29となります。

2

新しい質問への回答

2022/05/17 14:52

投稿

actorbug
actorbug

スコア2226

test CHANGED
@@ -1,3 +1,13 @@
1
+ Zuishinさんが別回答のコメントでおっしゃっている通り、`AMax * (double)ARatio`の結果はdoubleで、`AMax * ARatio`の結果はfloatです。([参考URL](https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/expressions#11473-binary-numeric-promotions))
2
+
3
+ 計算結果は正しくは29.0000009536743ですが、floatの精度では表現できない数値なので、丸められて29となります。
4
+
5
+ ---
6
+ 以下は、修正前の質問に対する回答になります。
7
+
8
+
9
+
10
+
1
11
  float型で表現可能な29の次に大きい数値を求めて、double型に変換すれば、似たような結果にはなります。([参考URL](https://stackoverflow.com/questions/9485943/calculate-the-unit-in-the-last-place-ulp-for-doubles))
2
12
  ```c#
3
13
  using System;

1

両者が同じ数値であることの明示、余計な愚痴の削除

2022/05/17 13:58

投稿

actorbug
actorbug

スコア2226

test CHANGED
@@ -22,8 +22,7 @@
22
22
 
23
23
  ただ、見ての通り、floatで表現可能な29の次に大きい数値をdoubleに変換しても29.0000019073486にしかならないので、29.0000009536743になるというのは何かの間違いではないでしょうか。
24
24
 
25
+ なお、ここで求めたfloat値とdouble値は、誤差なく完全に同じ数値です。
25
- さて、ここで求めたfloat値`ToString()`したときに`29`と表示される理由ですが、`ToString()`の仕様なります。
26
+ それなのにfloat値だけ`29`と表示されてしまうのは、`ToString()`の仕様が原因となります。
27
+
26
28
  `ToString()`に数値書式指定文字列を与えない場合のデフォルトは`"G"`であり([参考URL](https://docs.microsoft.com/ja-jp/dotnet/api/system.single.tostring?view=net-6.0))、`"G"`に精度を指定しない場合のデフォルトは[floatの場合7桁](https://docs.microsoft.com/ja-jp/dotnet/standard/base-types/standard-numeric-format-strings#general-format-specifier-g)なので、`29`と表示されます。
27
-
28
- ・・・とここまで書いて確認したら、質問が書き換えられていてショックです。
29
- もったいないのでそのまま回答として出しておきます。