私の最後の目標は、常に最も近い偶数の整数に丸めることです。
たとえば、1122.5196
という結果は1122
という結果になります。私はこのオプションを試しました:
Math.Round(1122.5196d, 0, MidpointRounding.ToEven); // result 1123
Math.Round(1122.5196d, 0, MidpointRounding.AwayFromZero); // result 1123
最後に、私が取得したいのは、常に最も近い偶数の整数です。例えば:
1122.51 --> 1122
1122.9 --> 1122
(最も近いintは1123
ですが、oddであり、1122
はnearer1124
よりも大きいため)1123.0 --> 1124
(次の偶数値、次のより高い偶数値)正の数でのみ動作します。
等々。
それを行う方法はいくつかありますか、独自の方法を実装する必要がありますか?
これを試してください(「next偶数値」を取得するためにMath.Round
でMidpointRounding.AwayFromZero
を使用しますが、scaled-2
factor):
double source = 1123.0;
// 1124.0
double result = Math.Round(source / 2, MidpointRounding.AwayFromZero) * 2;
デモ:
double[] tests = new double[] {
1.0,
1123.1,
1123.0,
1122.9,
1122.1,
1122.0,
1121.5,
1121.0,
};
string report = string.Join(Environment.NewLine, tests
.Select(item => $"{item,6:F1} -> {Math.Round(item / 2, MidpointRounding.AwayFromZero) * 2}"));
Console.Write(report);
結果:
1.0 -> 2 // In case of tie, next even value
1123.1 -> 1124
1123.0 -> 1124 // In case of tie, next even value
1122.9 -> 1122
1122.1 -> 1122
1122.0 -> 1122
1121.5 -> 1122
1121.0 -> 1122 // In case of tie, next even value
一発ギャグ:
double RoundToNearestEven(double value) =>
Math.Truncate(value) + Math.Truncate(value) % 2;
説明:浮動小数点の後にいくつかの数字がある偶数がある場合、それらの数字を取り除く必要があります。奇数がある場合、同じことをしてから、偶数であることが保証されている次の整数に移動する必要があります。
追伸@DmitryBychenkoに、ダブルキャストからロングキャストまでが最も賢明なアイデアではないことを指摘してくれてありがとう。
使用しても結果が1123になる理由
Math.Round(1122.5196d, 0, MidpointRounding.ToEven);
それはまさにあなたがコンパイラーに行うように頼んだことだからです。小数で偶数に丸める場合、1123.0は偶数であることを忘れないでください。
すなわち。偶数に丸められた1122.51は1123.0になります(10進数であるため、常に小数点以下の桁が保持されるため、ここで.0を指定すると偶数になります)。
代わりに、これを行う関数を作成しますsomething like:
private int round_up_to_even(double number_to_round)
{
int converted_to_int = Convert.ToInt32(number_to_round);
if (converted_to_int %2 == 0) { return converted_to_int; }
double difference = (converted_to_int + 1) - number_to_round;
if (difference <= 0.5) { return converted_to_int + 1; }
return converted_to_int - 1;
}
Msdnで見つかった関数の例を次に示します。これは、最も近い数字でさえも、あなたのケースにうまく収まるようです。
using System;
class Example
{
public static void Main()
{
// Define a set of Decimal values.
decimal[] values = { 1.45m, 1.55m, 123.456789m, 123.456789m,
123.456789m, -123.456m,
new Decimal(1230000000, 0, 0, true, 7 ),
new Decimal(1230000000, 0, 0, true, 7 ),
-9999999999.9999999999m,
-9999999999.9999999999m };
// Define a set of integers to for decimals argument.
int[] decimals = { 1, 1, 4, 6, 8, 0, 3, 11, 9, 10};
Console.WriteLine("{0,26}{1,8}{2,26}",
"Argument", "Digits", "Result" );
Console.WriteLine("{0,26}{1,8}{2,26}",
"--------", "------", "------" );
for (int ctr = 0; ctr < values.Length; ctr++)
Console.WriteLine("{0,26}{1,8}{2,26}",
values[ctr], decimals[ctr],
Decimal.Round(values[ctr], decimals[ctr]));
}
}
// The example displays the following output:
// Argument Digits Result
// -------- ------ ------
// 1.45 1 1.4
// 1.55 1 1.6
// 123.456789 4 123.4568
// 123.456789 6 123.456789
// 123.456789 8 123.456789
// -123.456 0 -123
// -123.0000000 3 -123.000
// -123.0000000 11 -123.0000000
// -9999999999.9999999999 9 -10000000000.000000000
// -9999999999.9999999999 10 -9999999999.9999999999
「中間点の値を丸めるとき、丸めアルゴリズムは等価性テストを実行します。浮動小数点形式のバイナリ表現と精度の問題のため、メソッドによって返される値は予期しないものになる可能性があります。」