如何逐一增加小数的最小小数部分?

Gus*_*son 9 c# math decimal

我想用一个增加十进制的最小小数部分,例如

decimal d = 0.01
d++
d == 0.02
Run Code Online (Sandbox Code Playgroud)

要么

decimal d = 0.000012349
d++
d == 0.000012350
Run Code Online (Sandbox Code Playgroud)

我该怎么做呢?

Joe*_*Joe 12

十进制类型(.NET 2.0及更高版本)保留重要的尾随零,这是计算结果或解析字符串的结果.例如1.2*0.5 = 0.60(将两个数字精确地乘以一个小数位,即使第二个小数位为零,也能精确到2位小数):

decimal result = 1.2M * 0.5M;
Console.WriteLine(result.ToString()); // outputs 0.60
Run Code Online (Sandbox Code Playgroud)

以下假设您要考虑十进制值中的所有有效数字,即

decimal d = 1.2349M;       // original  1.2349;
d = IncrementLastDigit(d); // result is 1.2350;
d = IncrementLastDigit(d); // result is 1.2351; (not 1.2360).
Run Code Online (Sandbox Code Playgroud)

但是,如果您想首先删除尾随零,则可以这样做,例如使用此答案中的技术.

没有内置的东西可以做到这一点.你必须自己做(a)确定小数点后有多少位数,然后(b)加上适当的数量.

要确定小数点后有多少位数,您可以将其格式化为字符串,然后对它们进行计数,或者更有效地调用decimal.GetBits(),其结果是包含缩放因子的四个整数的数组.第四个整数的16-23位.

完成后,您可以轻松计算要添加到小数值的所需值.

这是一个使用GetBits的实现,对于负数IncrementLastDigit(-1.234M)=> -1.235M,它从零开始"递增".

static decimal IncrementLastDigit(decimal value)
{
    int[] bits1 = decimal.GetBits(value);
    int saved = bits1[3];
    bits1[3] = 0;   // Set scaling to 0, remove sign
    int[] bits2 = decimal.GetBits(new decimal(bits1) + 1);
    bits2[3] = saved; // Restore original scaling and sign
    return new decimal(bits2);
}
Run Code Online (Sandbox Code Playgroud)

或者这里是另一种选择(可能稍微优雅一点):

static decimal GetScaledOne(decimal value)
{
    int[] bits = decimal.GetBits(value);
    // Generate a value +1, scaled using the same scaling factor as the input value
    bits[0] = 1;
    bits[1] = 0;
    bits[2] = 0;
    bits[3] = bits[3] & 0x00FF0000;
    return new decimal(bits);
}

static decimal IncrementLastDigit(decimal value)
{
    return value < 0 ? value - GetScaledOne(value) : value + GetScaledOne(value);
}
Run Code Online (Sandbox Code Playgroud)