数値を小数点以下第 1 位に丸めようとしていますが、さまざまな MidpointRounding オプションを考慮すると、うまく機能しているようです。ただし、その数値が四捨五入に算術的に影響する小数点以下の桁数が連続している場合、問題が発生します。
例:
で0.1
、0.11..0.19
それ0.141..0.44
は動作します:
Math.Round(0.1, 1) == 0.1
Math.Round(0.11, 1) == 0.1
Math.Round(0.14, 1) == 0.1
Math.Round(0.15, 1) == 0.2
Math.Round(0.141, 1) == 0.1
しかし、0.141..0.149
常に を返しますが0.1
、0.146..0.149
丸める必要があります0.2
:
Math.Round(0.145, 1, MidpointRounding.AwayFromZero) == 0.1
Math.Round(0.146, 1, MidpointRounding.AwayFromZero) == 0.1
Math.Round(0.146, 1, MidpointRounding.ToEven) == 0.1
Math.Round(0.146M, 1, MidpointRounding.ToEven) == 0.1M
Math.Round(0.146M, 1, MidpointRounding.AwayFromZero) == 0.1M
この問題に対処する関数を考え出そうとしましたが、この場合はうまく機能しますが、0.144449
最初の10進数に丸めようとするともちろん失敗します(これは である必要があります0.2
が、結果は0.1
.)(それはありませんMath.Round() でも動作しません。)
private double "round"(double value, int digit)
{
// basically the old "add 0.5, then truncate to integer" trick
double fix = 0.5D/( Math.Pow(10D, digit+1) )*( value >= 0 ? 1D : -1D );
double fixedValue = value + fix;
// 'truncate to integer' - shift left, round, shift right
return Math.Round(fixedValue * Math.Pow(10D, digit)) / Math.Pow(10D, digit);
}
解決策は、すべての数字を列挙し、4 より大きい最初の値を見つけてから切り上げるか、切り捨てることだと思います。問題 1: それはばかげているように思えます。問題 2: 無数の乗算と減算を行わずに数字を列挙する方法がわかりません。
簡単に言えば、それを行うための最良の方法は何ですか?