可变小数舍入

Variable decimal rounding

情况如下:

输入:

var a = 1.2567789m;
var b = 1.898436216m;
var c = 1.79863m;

var aD = 2;
var bD = 3;
var cD = 1;

结果:

var aR = 1.25m;  
var bR = 1.898m;
var cR = 1.7m;

所以输入的是不同的十进制数,小数位数不同,需要的小数位数也不同。我需要按小数位数向下舍入输入数字,每次都可能不同。我为此编写了一个工作正常的方法,但我想知道是否有更好的解决方案:

    static void Main(string[] args)
            {
                var a = 1.2567789m;
                var b = 1.898436216m;
                var c = 1.79863m;
    
                var aD = 2;
                var bD = 3;
                var cD = 1;
    
                Console.WriteLine(RoundDown(a, aD));
                Console.WriteLine(RoundDown(b, bD));
                Console.WriteLine(RoundDown(c, cD));
                Console.ReadLine();
            }
    
            private static decimal RoundDown(decimal number, int decimals)
            {
                switch (decimals)
                {
                    case 1:
                    {
                        return (Math.Truncate(number * 10)) / 10;
                    }
                    case 2:
                    {
                        return Math.Truncate(number * 100) / 100;
                    }
                    case 3:
                    {
                        return Math.Truncate(number * 1000) / 1000;
                    }
                    case 4:
                    {
                        return Math.Truncate(number * 10000) / 10000;
                    }
                    case 5:
                    {
                        return Math.Truncate(number * 100000) / 100000;
                    }
                    case 6:
                    {
                        return Math.Truncate(number * 1000000) / 1000000;
                    }
                    case 7:
                    {
                        return (Math.Truncate(number * 10000000)) / 10000000;
                    }
                    case 8:
                    {
                        return Math.Truncate(number * 100000000) / 100000000;
                    }
                    case 9:
                    {
                        return Math.Truncate(number * 1000000000) / 1000000000;
                    }
                    case 10:
                    {
                        return Math.Truncate(number * 10000000000) / 10000000000;
                    }
                    default: return 0;
                }
            }

非常感谢您

您可以在循环中计算 10 ** digits;然后缩放,计算 Floor 并缩减:

代码:

private static decimal MyFloor(decimal value, int digits = 0) {
  decimal power = 1;
        
  for (int i = 0; i < digits; ++i)
    power = digits >= 0 ? power * 10 : power / 10;

  return Math.Floor(value * power) / power;
}

演示:

var tests = new (decimal value, int digits)[] {
  (1.2567789m, 2),
  (1.898436216m, 3),
  (1.79863m, 1)
};

string report = string.Join(Environment.NewLine, tests
  .Select(test => $"Floor({test.value}, {test.digits}) = {MyFloor(test.value, test.digits)}"));

Console.WriteLine(report);

结果:

Floor(1.2567789, 2) = 1.25
Floor(1.898436216, 3) = 1.898
Floor(1.79863, 1) = 1.7

这些你都需要

Math.Round()
Math.Floor()
Math.Ceiling()

虽然 Dimitry 的回答一如既往的出色 Math.Round 是完成这项工作的工具:

foreach( var x in new [] {( V: 1.2567789m, D: 2),(V: 1.898436216m, D: 3),(V: 1.79863m, D: 1)})
    Console.WriteLine($"{x.V} @ {x.D} = {Math.Round(x.V, x.D, MidpointRounding.ToZero)}");

这会产生:

1.2567789 @ 2 = 1.25
1.898436216 @ 3 = 1.898
1.79863 @ 1 = 1.7