次のテストは失敗しますC#
Assert.AreEqual<double>(10.0d, 16.1d - 6.1d);
問題は浮動小数点エラーのようです。
16.1d - 6.1d == 10.000000000000002
これは、 を使用するコードの単体テストを作成する際に頭を悩ませていますdouble
。これを修正する方法はありますか?
次のテストは失敗しますC#
Assert.AreEqual<double>(10.0d, 16.1d - 6.1d);
問題は浮動小数点エラーのようです。
16.1d - 6.1d == 10.000000000000002
これは、 を使用するコードの単体テストを作成する際に頭を悩ませていますdouble
。これを修正する方法はありますか?
私はアンダース・アベルに同意します。浮動小数点数表現を使用してこれを行う方法はありません。IEE 1985-754
の直接の結果では、表現
できる数値のみを
格納して正確に計算できます (選択したビット数がこれを許可する限り)。
例: 1024 * 1.75 * 183.375 / 1040.0675 <-- 正確に保存されます
10 / 1.1 <--
正確に保存され
ません 有理数の正確な表現にほとんど関心がない場合は、分数を使用して独自の数値実装を作成できます。
これは、分子、分母、および符号を保存することで実行できます。次に、乗算、減算などの演算を実装する必要があります (良好なパフォーマンスを確保するのは非常に困難です)。toString() メソッドは次のようになります (cachedRepresentation、cachedDotIndex、および cachedNumerator がメンバー変数であると仮定します)。
public String getString(int digits) {
if(this.cachedRepresentation == ""){
this.cachedRepresentation += this.positiveSign ? "" : "-";
this.cachedRepresentation += this.numerator/this.denominator;
this.cachedNumerator = 10 * (this.numerator % this.denominator);
this.cachedDotIndex = this.cachedRepresentation.Length;
this.cachedRepresentation += ".";
}
if ((this.cachedDotIndex + digits) < this.cachedRepresentation.Length)
return this.cachedRepresentation.Substring(0, this.cachedDotIndex + digits + 1);
while((this.cachedDotIndex + digits) >= this.cachedRepresentation.Length){
this.cachedRepresentation += this.cachedNumerator / this.denominator;
this.cachedNumerator = 10 * (this.cachedNumerator % denominator);
}
return cachedRepresentation;
}
これは私にとってはうまくいきました。長い数値の操作自体で、データ型が小さすぎると問題が発生しました (通常、私は c# を使用しません)。経験豊富な c# 開発者にとって、小さなデータ型の問題なしにこれを実装することは問題ないと思います。
これを実装したい場合は、初期化時および操作の前に euclid maximum-common-divider を使用して分数の縮小を行う必要があります。
非有理数は、(私が知っているすべてのケースで)必要なだけ正確な表現に近づくアルゴリズムによって指定できます(そしてコンピューターが許可します)。