可逆十进制到双倍转换

时间:2016-10-18 14:33:01

标签: c# .net casting floating-point decimal

我很想知道您是否可以将decimal转换为double,但仍然能够回到我开始时的同一个decimal。当然,假设您使用15或更少的有效数字。基本上,你能指望这个:

decimal original = someValue;
double converted = ReversibleToDouble(original);
decimal result = BackToDecimal(converted);
if (original == result)
    Console.WriteLine("All is well with the world.");

如果没有这样的转换,我不介意ReversibleToDouble是否抛出异常,只要在成功完成后保证结果。现在,这是我所拥有的简单解决方案:

public static double ReversibleToDouble(decimal input)
{
    double output = (double)input;

    if ((decimal)output != input)
        throw new ArgumentException("Impossible to convert reversibly.", "input");

    return output;
}

public static decimal BackToDecimal(double input)
{
    return (decimal)input;
}

我对数值分析并不是很了解,所以我对此有几个问题。

第一个问题:在尝试任何转化之前,如果有少于15个有效数字,这种琐碎的方法可以保证不会引发异常吗?

如果没有,第二个问题:有没有办法让这项工作更有可能?

如果是,那么最后一个问题:这是否可行,而不是主修科学领域? :)

2 个答案:

答案 0 :(得分:0)

你做不到。

十进制是128位类型,double是64位类型,因此当从十进制转换为双精度时,您将丢失信息

答案 1 :(得分:0)

您要求的是找到将舍入到同一浮点数的最短十进制值。

这正是用于在scheme,java,python,Squeak / Pharo Smalltalk等中打印浮点的算法...

所以答案是肯定的,我们通常可以,只要没有太多的小数。现在不要问普遍和总体上的区别,我不确定我能否轻易回答这个问题。

在Pharo Smalltalk中,您将使用消息asMinimalDecimalFraction来完成这项工作。 https://github.com/pharo-project/pharo-core/blob/6.0/Kernel.package/Float.class/instance/printing/asMinimalDecimalFraction.st

Smalltalk中的一个分数在c#中并不完全是十进制,因为它具有任意精度和任意分母,但上面的一些原则适用于两者。

另见

Count number of digits after `.` in floating point numbers?

Convert float to rounded decimal equivalent