【问题标题】:Reversible decimal to double conversion可逆十进制到双精度转换
【发布时间】:2017-02-27 21:27:40
【问题描述】:

我很想知道您是否可以将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 个,这种简单的方法是否可以保证工作而不会引发异常?

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

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

【问题讨论】:

  • 我认为这是一个很好的问题(数值分析很难),但我不明白为什么可以通过舍入从decimal 丢失信息,但不能通过舍入来丢失它执行到double 的天真转换。
  • @MichaelBurr 好点。我实际上添加了那个位,因为我知道双打的精度更有限,但实际上我不会真正使用这么多数字。基本上,我对这些转换的属性以及我是否可以信任这种相等性检查更感兴趣的是相对“简单”的数字,这些数字在以二进制表示时可能看起来很糟糕。我完全可以解决这个问题,我只是想知道问题是否存在。如果这是有道理的。
  • 这通常是不可能的。改变值的是从基数 10 到基数 2 的转换。只有当十进制数是 2 的幂的有限和时,这种转换才能完美。所以二进制值中有有限数量的 1 和 0。如果不是,则转换会产生无限位数。这必然会被截断,因为 double 只能存储 53 位。将该值转换回十进制将在第 15 位之后产生不同的十进制数字。
  • @HansPassant:确实(假设避免了下溢和上溢)15 位小数可以通过(1)转换为 IEEE 754 binary64 浮点数来准确恢复 -点使用四舍五入,然后 (2) 使用四舍五入转换回 15 位十进制格式。 OP 提出的建议比这稍微复杂一些,因为它涉及转换回更高精度的十进制格式,然后将结果四舍五入回到 15 位,从而引入了双重四舍五入的潜在问题。但至少有足够的回旋余地,这应该仍然有效。
  • 更多信息在这里:exploringbinary.com/…

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


【解决方案1】:

您的要求就像找到将四舍五入到相同浮点数的最短十进制值。

这正是用于在 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

【讨论】:

    【解决方案2】:

    你不能。

    Decimal 是 128 位类型,double 是 64 位类型,所以从十进制转换为双精度时会丢失信息

    【讨论】:

    • 这就是为什么我问如果我将小数四舍五入到 15 位有效数字是否可以保证工作,否则。我会强调一下。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-07
    相关资源
    最近更新 更多