在c#中执行两位小数的除法时,如果真正的数学结果不能精确地存储为十进制类型,则结果的最后一位将自动舍入。
我想编写一个执行除法的函数,即使最后一位数字总是向下舍入,即使最后一位数字通常会导致向上舍入。
我的函数将被声明为MyDivide(十进制a,十进制b)
例如MyDivide(2.0M,3.0M)=> 0.6666666666666666666666666666
而c#除法运算符将产生2.0M / 3.0M => 0.6666666666666666666666666667
感谢您提供任何帮助。
答案 0 :(得分:3)
您将不得不自己实施long division。没有办法让内置部门为你做这件事(提示:你无法区分2m / 3m
和.6666666666666666666666666667m / 1m
或6666666666666666666666666667m / 10000000000000000000000000000m
。
答案 1 :(得分:2)
没有简单的方法让它按照你想要的方式划分,但是你可以检测到舍入并对其进行校正。由于decimal
的尾数是96位,因此您无法将其保留在long
或double
中,因此我使用.Net 4 BigInteger
对象。我只是将分母和商的尾数相乘,并将其与分子进行比较(根据乘法结果的指数进行调整)。如果结果大于分子,那么除法必须从零舍入,所以我只需要从商中减去最低位的1。为此,我创建了一个十进制小数,其尾数为1,指数为指数的指数。
using System;
using System.Numerics;
using System.Collections.Generic;
namespace DivTest
{
class Divide
{
public static decimal MyDivide(decimal numerator, decimal denominator)
{
var quotient = numerator / denominator;
// turn decimals into mantissas (BigInts) and exponents
int nExp, dExp, qExp;
var nMan = MantissaOfDecimal(num, out nExp);
var dMan = MantissaOfDecimal(denom, out dExp);
var qMan = MantissaOfDecimal(quotient, out qExp);
// multiply quotient times denominator and compare with numerator
if (dMan * qMan > nMan * BigInteger.Pow(10, dExp + qExp - nExp))
{
// quotient was rounded away from zero, so subtract LSB
// to round back toward zero
quotient -= new decimal(1, 0, 0, quotient < 0, (byte)qExp);
}
return quotient;
}
static BigInteger MantissaOfDecimal(decimal d, out int exponent)
{
var ints = decimal.GetBits(d);
exponent = (ints[3] >> 16) & 0xFF;
var bytes = new List<byte>(13);
// create a BigInteger containing the mantissa of the decimal value
bytes.AddRange(BitConverter.GetBytes(ints[0]));
bytes.AddRange(BitConverter.GetBytes(ints[1]));
bytes.AddRange(BitConverter.GetBytes(ints[2]));
bytes.Add(0); // avoid high bits being interpreted as negative
return new BigInteger(bytes.ToArray());
}
static void Main()
{
decimal num = 2m, denom = 3m;
Console.WriteLine("Divide: " + num / denom);
Console.WriteLine("MyDivide: " + MyDivide(num, denom));
}
}
}
上述程序的输出是:
Divide: 0.6666666666666666666666666667 MyDivide: 0.6666666666666666666666666666