誰でもこの奇妙さを説明できますか:
Dim result as single = 0
result = CType("8.01", Single) * 100 ' result=801.0 as expected
result = CType("8.02", Single) * 100 ' result=802.000061 --- not expected
上記に加えて
result = 8.02 * 100 ' result = 802.0 as expected
誰でもこの奇妙さを説明できますか:
Dim result as single = 0
result = CType("8.01", Single) * 100 ' result=801.0 as expected
result = CType("8.02", Single) * 100 ' result=802.000061 --- not expected
上記に加えて
result = 8.02 * 100 ' result = 802.0 as expected
Single
(またはfloat
) は有効数字が 7 桁しかないため、有効数字を超えて印刷される可能性のあるものはすべて、とにかくほとんど偽物です。これは、浮動小数点演算の通常のアーティファクトです。数値の小数点以下 4 桁までしか信頼できません (有効数字 3 桁はすでに小数点の前にあるため)。
さらに詳しく説明すると、数値 8.01 と 8.02 はバイナリ ストレージを使用して正確に表すことはできません (0.01 も 0.02 も 1/2 nの形式の分数の和では正確に表すことができないため)。詳細は数値によって異なる場合がありますが、そのような数値を使用すると、通常の精度範囲外の余分な数字が表示される場合があります。
これは、801 と 802を正確に表すことができるという事実には影響しませんが、この場合、開始する正確な数はありません。
ETA:実際、計算を直接含めたときに表示されるのは、まさにこれです。コンパイラが計算を評価802
し、プログラムに書き込むだけです。これを確認するには、Reflector を使用します。また、ソース コードの浮動小数点リテラルはDouble
デフォルトである可能性が高いため、ここから始めると精度が大幅に向上します。の場合result
はSingle
this にダウンキャストされSingle
、小数点以下 16 桁目のエラーは収まらないため単純に破棄されSingle
ます。
これは、浮動小数点数がメモリ内で表現される方法の制限によるものです。完全なローダウンについては、ウィキペディアのページを読んでください。これはエラーでも、.net に固有のものでもありません。
EDIT:これらの2つの記事も一見の価値があります(後者は数学が重いです)。
浮動小数点値の比較が必要な場合は、こちらを参照してください:浮動小数点値の比較
Single
およびDouble
.NET では浮動小数点数として表されますが、残念ながらこれらの種類の数値を格納することは正確ではありません。'Single' と 'Double' の数値を扱う場合、わずかな差異が生じます。
ただし、別の方法があります。.NET には、Decimal
これらの数値をより適切に処理できる型があります。まだ完全ではありません ( http://www.yoda.arachsys.com/csharp/decimal.htmlを参照してください - 特に最後の段落を参照)。