なぜ注文の影響を四捨五入の追加時に複数のdoubleクライアントまで、フルのC#
-
22-08-2019 - |
質問
考え、以下のC#コード:
double result1 = 1.0 + 1.1 + 1.2;
double result2 = 1.2 + 1.0 + 1.1;
if (result1 == result2)
{
...
}
result1常に等しいresult2。このことがするものではありません.result1は3.3とresult2は3.3000000000000003.唯一の違いは定数.
知っているdoubleを行うに丸め問題が発生する可能性があります。う意識が使用できます部で"年"、小数部で"くれば必要な絶対精度。または使用できますMath.Round()は私の場合です。だけなんですけどねぎ人をつかのC#コンパイラしています。誰でもできるので教えてくれますか?
編集:
皆さん、ありがとうござ誰かが読み上に浮動小数点演算および/または話題の固有誤差をどのようにCPUが表示されます。しかし、主にスラストの私の質問はまだ未解決のままです。僕の故障のためな語句を用い、正しく表してください。私がこのように:
破壊され、上記のコードを参考にして設定は、以下の操作をする:
double r1 = 1.1 + 1.2;
double r2 = 1.0 + r1
double r3 = 1.0 + 1.1
double r4 = 1.2 + r3
その上で追加した丸め誤差(番号e1..e4).いr1含まれ四捨五入の誤差e1,r2含まれ四捨五入の誤差e1+e2,r3を含むe3及びr4を含むe3+e4.
現在、わからないかを正確にどのように丸め誤差を起こしてください予e1+e2等e3+e4.明確なものと思われるかが間違いだった。もう一つは、私の上にコードが付かないの丸め誤差.その思いはC#のコンパイラことになるであろうかではなく、CPUを搭載しています。
かんに聞くと、おそらく最高の答えは誰にでもできるのですが、博士号CPUの設計もっさんお願いします。
編集2
のILから独自のコードサンプルで明らかでコンパイラのCPUを行なっているのがこの
.method private hidebysig static void Main(string[] args) cil managed
{
.entrypoint
.maxstack 1
.locals init (
[0] float64 result1,
[1] float64 result2)
L_0000: nop
L_0001: ldc.r8 3.3
L_000a: stloc.0
L_000b: ldc.r8 3.3000000000000003
L_0014: stloc.1
L_0015: ret
}
のコンパイラの追加に番号をふんだんに練り込んだ
解決
私が期待されていe1+e2等e3+e4.
それは完全とは異なり期待
floor( 5/3 ) + floor( 2/3 + 1 )
に等しくなければな
floor( 5/3 + 2/3 ) + floor( 1 )
を除いを乗じ2^53る前に。
12ビット精度の浮動小数点や前方一致のお値:
1.0 = 1.00000000000 1.1 = 1.00011001100 1.2 = 1.00110011001 1.0 + 1.1 = 10.00011001100 // extended during sum r1 = 1.0 + 1.1 = 10.0001100110 // truncated to 12 bit r1 + 1.2 = 11.01001100101 // extended during sum r2 = r1 + 1.2 = 11.0100110010 // truncated to 12 bit 1.1 + 1.2 = 10.01001100110 // extended during sum r3 = 1.1 + 1.2 = 10.0100110011 // truncated to 12 bit r3 + 1.0 = 11.01001100110 // extended during sum r4 = r3 + 1.0 = 11.0100110011 // truncated to 12 bit
その順序を変更する業務/truncations原因のエラーの変更、およびr4!= r2.を追加する場合1.1および1.2このシステムのアリーナ、日産スタジアムに行くなった部分一致です。を追加した場合、1.0-1.1のアリーナ、日産スタジアムが1.1が失われ、その結果は同じではありません。
一つの注文は四捨五入(前方一致)を削除し、末尾 1
.
その他の注文を丸めを削除し、末尾 0
している。
一つてないゼロその誤差は同じではありません。
兼ねてより多くのビットの、C#う丸よりも前方一致でこの単純なモデルできな誤りが起こる可能性が異なる秩序と同じ値です。
の違いfpと数学では以下の表記追加しラウンド"だけではなく。
他のヒント
のc#コンパイラのないものです。CPUのです。
また、CPUの登録、その後の追加の結果、保存されることを登録するA+Bの近似の精度浮動小数使用
そこで追加のエラーを追加します。このエラーのほか、ではない他の操作とは、最終ます。
見 クラシック紙(コンピュータ科学者にとって知っておくべきこ浮動小数点演算) 用になれます。このようなものがどのようになるかと浮動小数点演算.ではコンピューター科学者にお伝えすること1/3+1/3+1/3 申し 1...
めの浮動小数点が重要になります。なお答えがしなければなりません注意するとの比較浮動小数点数です。で通常のを含め公差:
double epsilon = 0.0000001;
if (abs(result1 - result2) <= epsilon)
{
...
}
このと思われる: どのコンピュータ科学者にとって知っておくべきこ浮動小数点演算
なぜ、正確な同じ順序で説明できるの別の例です。
ということかと大変お手数ですが、下記10ので、店舗のすべての番号なので、店内は1、2、3、などを含む10が、その後10日でできるだけ屋毎秒数による内部損失の精度、すなわちはできるだけ店10,12,14。
現在、この例では、長短を付けすぎないように注意以下の生異なる結果:
1 + 1 + 1 + 10 = 12 (or 14, depending on rounding)
10 + 1 + 1 + 1 = 10
の問題を浮動小数点数とすることができませんで表される正確に、エラーなので、常に同じようにします。
例えば、3.00000000003+3.00000000003たち6.00000000005(お知らせない6のが3.00000000003+2.99999999997たち6.00000000001、そ:
step 1: 3.00000000003 + 3.00000000003 = 6.00000000005
step 2: 6.00000000005 + 2.99999999997 = 9.00000000002
でも、変更の順:
step 1: 3.00000000003 + 2.99999999997 = 6.00000000001
step 2: 6.00000000001 + 3.00000000003 = 9.00000000004
です。
今はもちろんされることもありますので、ラッキーが上記の例はバランスになっている、最初のネゴランドまでです。xxx1ウンその他。xxx1えます。xxx3の両方が保証されません。
て実際に使用しないのと同じ値にするためには結果が異なる:
double result1 = 2.1 + 1.2;
double result2 = 2.2 + 1.1;
で倍かを表す数値を正確に取得す。