我的最后一个目标总是四舍五入到最接近偶数。
例如,我要作为结果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
(因为最接近的整数是1123
,但它是 odd ,并且1122
比<{{1 }})1124
(下一个偶数值,下一个更高偶数值)我只使用正数。
以此类推。
有些方法可以做到这一点,或者我应该实现自己的方法?
答案 0 :(得分:64)
尝试此操作(让Math.Round
与MidpointRounding.AwayFromZero
一起使用,以获得“ next 偶数”,但已缩放-2
因素):
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
答案 1 :(得分:7)
一个班轮:
double RoundToNearestEven(double value) =>
Math.Truncate(value) + Math.Truncate(value) % 2;
说明:如果我们在浮点数后有一个偶数且有一些数字,我们只需要除去这些数字即可。如果我们有奇数,则需要执行相同的操作,然后移至保证为偶数的下一个整数。
P.S。感谢@DmitryBychenko指出,将双倍转换为长距离并不是最明智的选择。
答案 2 :(得分:3)
即使使用
也会得到结果1123的原因Math.Round(1122.5196d, 0, MidpointRounding.ToEven);
是因为这正是您要求编译器执行的操作。在使用小数点舍入到偶数时,请务必记住1123.0是偶数。
即。将1122.51舍入为偶数将变为1123.0(请注意,由于它是小数,因此将始终保留其小数位,因此此处的.0使其成为偶数)。
相反,我会写一个函数来做到这一点,类似:
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;
}
答案 3 :(得分:0)
这是我在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
“在对中点值进行四舍五入时,四舍五入算法将执行相等性测试。由于二进制表示形式和浮点格式的精度问题,该方法返回的值可能是意外的。”
答案 4 :(得分:0)
@马克 您的代码段与Excel计算不匹配。 在Excel中,尝试以下值:
-2,98-> -4
使用您的代码:
我修改了代码,现在可以正常工作:
public static double round_up_to_even(double number_to_round)
{
var converted_to_int = Convert.ToDouble(number_to_round);
if (converted_to_int %2 == 0) return Math.Round(converted_to_int, 0);
var difference = (converted_to_int + 1) - number_to_round;
if (difference <= 0.5) return Math.Round(converted_to_int + 1, 0);
var vOffset=converted_to_int < 0 ? -1 : 1;
return Math.Round(converted_to_int + vOffset, 0);
}