首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >双到十进制,15位后不舍入

双到十进制,15位后不舍入
EN

Stack Overflow用户
提问于 2014-07-05 13:37:06
回答 2查看 2.5K关注 0票数 7

当将“高”精度双倍转换为十进制时,由于四舍五入,我失去了Convert.ToDecimal或浇铸到(十进制)的精度。

例子:

代码语言:javascript
复制
double d = -0.99999999999999956d;
decimal result = Convert.ToDecimal(d); // Result = -1
decimal result = (Decimal)(d); // Result = -1

Convert.ToDecimal(double)返回的十进制值最多包含15个有效数字。如果value参数包含超过15个有效位数,则使用四舍五入对其进行舍入。

因此,为了保持精度,我必须将双字符串转换为字符串,然后调用Convert.ToDecimal( String ):

代码语言:javascript
复制
decimal result = System.Convert.ToDecimal(d.ToString("G20")); // Result = -0.99999999999999956d

这个方法是有效的,但我想避免使用字符串变量来将一个双值转换为十进制,而不会在15位后舍入?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2014-07-05 13:58:24

一种可能的解决方案是将d分解为n个双倍的精确和,其中最后一个是小的,包含转换为十进制时想要的所有尾随的重要数字,而第一个(n-1)则精确地转换为十进制。

对于源-1.0到1.0之间的双d

代码语言:javascript
复制
    decimal t = 0M;
    bool b = d < 0;
    if (b) d = -d;
    if (d >= 0.5) { d -= 0.5; t = 0.5M; }
    if (d >= 0.25) { d -= 0.25; t += 0.25M; }
    if (d >= 0.125) { d -= 0.125; t += 0.125M; }
    if (d >= 0.0625) { d -= 0.0625; t += 0.0625M; }
    t += Convert.ToDecimal(d);
    if (b) t = -t;

在ideone.com上进行测试。

请注意,d -=操作是精确的,即使C#以比double更高的精度计算二进制浮点操作(这是允许自己执行的)。

这比从double到string的转换更便宜,并且在结果中提供了几个额外的精度数字(上述四个如果-然后的结果提供了四位精度)。

备注:如果C#不允许自己以更高的精度进行浮点计算,那么一个很好的技巧就是使用Dekker分裂将d拆分成两个值d1d2,将每个值都精确地转换为十进制。唉,Dekker分裂只对IEEE 754乘法和加法有严格的解释。

另一种思路是利用C#的弗雷克斯版本得到d的意义和指数e,并计算(Decimal)((long) (s * 4503599627370496.0d)) * <however one computes 2^e in Decimal>

票数 4
EN

Stack Overflow用户

发布于 2014-07-08 17:12:33

有两种方法,一种适用于2^63以下的值,另一种适用于大于2^53的值。

将较小的值分割成整数和小数部分。整数部分可以精确地转换到long,然后Decimal注意到直接转换到Decimal可能不精确!分数部分可精确乘以9007199254740992.0 (2^53),转换为long,然后再转换为Decimal,再除以9007199254740992.0m。将该除法的结果添加到整数部分应该会产生一个Decimal值,该值在正确的最小显着数字内,可能不会被精确舍入,但仍然会比内置转换好得多!

对于较大的值,乘以(1.0/281474976710656.0) (2^-48),取结果的整数部分,再乘以281474976710656.0,然后从原来的结果中减去它。将除法和减法的整数结果转换为Decimal (它们应该精确地转换),将前者乘以281474976710656m,再加上后者。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/24586969

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档