【发布时间】: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