「.NETのfloat.Epsilon定数は計算機イプシロンではない」の版間の差分
ナビゲーションに移動
検索に移動
imported>Administrator |
imported>Administrator |
||
1行目: | 1行目: | ||
C#においてfloat型(Single型)の[[絶対値]]をfloat.Epsilon定数と比較している箇所の挙動がどうもおかしい。 | C#においてfloat型(Single型)の[[絶対値]]をfloat.Epsilon定数と比較している箇所の挙動がどうもおかしい。 | ||
+ | == 原因 == | ||
[[ググって]][[MSDN]]を見るとサラッと絶望的なひとことメモが。 | [[ググって]][[MSDN]]を見るとサラッと絶望的なひとことメモが。 | ||
The value of the F:System.Single.Epsilon property is not equivalent to machine epsilon, | The value of the F:System.Single.Epsilon property is not equivalent to machine epsilon, | ||
7行目: | 8行目: | ||
要約すると「浮動小数点演算の丸の相対誤差の上限(丸め誤差発生時にズレるであろう最大値)」であり「[[計算機イプシロン]]」ではない。 | 要約すると「浮動小数点演算の丸の相対誤差の上限(丸め誤差発生時にズレるであろう最大値)」であり「[[計算機イプシロン]]」ではない。 | ||
+ | |||
名前紛らわしすぎだろ。 | 名前紛らわしすぎだろ。 | ||
+ | == 解決 == | ||
「奥村晴彦『C言語による最新アルゴリズム事典』技術評論社,1991年,ISBN4-87408-414-1,2400円」という書籍に[[計算機イプシロン]]を動的に求める[[アルゴリズム]]が詳細に解説されており、また[[ソースコード]]は公式サイトにおいても配布されている。この本は非常に面白いので迷わず買え。 | 「奥村晴彦『C言語による最新アルゴリズム事典』技術評論社,1991年,ISBN4-87408-414-1,2400円」という書籍に[[計算機イプシロン]]を動的に求める[[アルゴリズム]]が詳細に解説されており、また[[ソースコード]]は公式サイトにおいても配布されている。この本は非常に面白いので迷わず買え。 | ||
https://oku.edu.mie-u.ac.jp/~okumura/algo/ | https://oku.edu.mie-u.ac.jp/~okumura/algo/ |
2018年2月15日 (木) 03:53時点における版
C#においてfloat型(Single型)の絶対値をfloat.Epsilon定数と比較している箇所の挙動がどうもおかしい。
原因
The value of the F:System.Single.Epsilon property is not equivalent to machine epsilon, which represents the upper bound of the relative error due to rounding in floating-point arithmetic. https://msdn.microsoft.com/ja-jp/library/system.single.epsilon(v=vs.110).aspx
要約すると「浮動小数点演算の丸の相対誤差の上限(丸め誤差発生時にズレるであろう最大値)」であり「計算機イプシロン」ではない。
名前紛らわしすぎだろ。
解決
「奥村晴彦『C言語による最新アルゴリズム事典』技術評論社,1991年,ISBN4-87408-414-1,2400円」という書籍に計算機イプシロンを動的に求めるアルゴリズムが詳細に解説されており、またソースコードは公式サイトにおいても配布されている。この本は非常に面白いので迷わず買え。 https://oku.edu.mie-u.ac.jp/~okumura/algo/
速攻でC#に移植した。
using System;
class MainClass
{
static float Foo(float x) { return x; }
static float MachineEpsilon()
{
int b, p;
float x, y, eps;
x = y = 2;
while (Foo(x + 1) - x == 1) x *= 2;
while (Foo(x + y) == x) y *= 2;
b = (int)(Foo(x + y) - x);
p = 1; x = b;
while (Foo(x + 1) - x == 1) { p++; x *= b; }
eps = 1;
while (Foo(1 + eps / 2) > 1) eps /= 2;
eps = Foo(1 + eps) - 1;
return eps;
}
public static void Main(string[] args)
{
Console.WriteLine("epsilon = {0}", MachineEpsilon());
}
}