问题 C#float到十进制转换


像这样转换浮点数的任何聪明方法:

float f = 711989.98f;

变成十进制(或双精度)而不失精度?

我试过了:

decimal d = (decimal)f;
decimal d1 = (decimal)(Math.Round(f,2));
decimal d2 = Convert.ToDecimal(f);

2905
2018-04-07 18:12


起源

更多细节:我正在与一个旧的Web服务接口,该服务发送这个巨大的对象,其中有一些字段为float。当我转换为十进制kaboom ...没有更多的便士! - Adrian4B
如果这是来自网络服务,它可能是XML,这意味着没有浮点数或小数 - 只是字符串。查看这些字符串转换为“内部”格式的位置 - mfeingold


答案:


现在为时已晚,第8位数字在编译器中丢失了。 float类型只能存储7位有效数字。你必须重写代码,分配为double或decimal当然会解决问题。


11
2018-04-07 18:22



谢谢我已经将映射对象上的字段类型从float更改为十进制,并解决了反序列化过程中发生的转换问题。 - Adrian4B


这可能是一个编译器错误,因为它似乎是一个有效的float应该直接转换为十进制。但它不会失去决心。 将125.609375从float转换为十进制将失去分辨率。 但是,将它从float转换为double然后将其转换为double将保持分辨率。

    float float_val = 125.609375f;

    decimal bad_decimal_val = (decimal)float_val;   //125.6094

    double double_val = (double)float_val;
    decimal good_decimal_val = (decimal)double_val;

3
2017-09-06 03:27





你有没有尝试过?

decimal.TryParse()

http://forums.asp.net/t/1161880.aspx

float / double和decimal之间没有隐式转换。隐式数字转换始终保证不会丢失精度或幅度,并且不会导致异常。


1
2018-04-07 18:16



不保证隐式转换不会失去精度。转换 9007199791611905 至 double 会屈服 9007199791611904。直接转换为 float 会屈服 9007200328482816。转换为 double 然后到 float 会屈服 9007199254740992 (如果数字直接转换为 float)。此外,虽然编译器允许隐式转换 float 至 double,这种转换比转换更有可能是错误的 double 至 float 这是不允许但应该是。 - supercat
@supercat显然 你可以无损转换 float 至 double。然而转换 double 至 float 可能会引入错误,具体取决于具体情况 double 有问题的价值。 - Drew Noakes
@DrewNoakes:如果使用迭代计算来使用类型计算对象的位置 double,然后希望使用接受的图形例程绘制它 float,转换为 float 即使保留,也会失去通常无用的精确度;削减精度几乎肯定会与程序员的意图一致。相反,如果某些代码,例如划分一个 int 要么 long 通过a float 并将结果存储在a中 double然后,除非程序员明确地将分割结果转换为 float我不认为程序员...... - supercat
...其实 意 分裂只应该用 float 精确。特定 int x=16777217; float y=1.0f; 你认为编写程序员的可能性更大吗? double z=x/y; 会期待的 z 是16777216.0还是16777217.0?就此而言,即使给出了 float one=1.0f,ten=10.0f; double d=one/ten;,你认为程序员更有可能会缺乏 d 得到0.1f或0.1的值? - supercat
@supercat,我明白你的意思了。我来到这个问题寻找有关从float / double转换为十进制时精度损失的信息(我正在考虑在deserialiser中允许这种转换,以便schemata可以这种方式发展),所以主要关注单个时期精度的损失转换。为此,我的评论成立。你的观点是有趣和有效的,虽然我知道的一个陷阱,并通过仔细选择浮点类型避免。我不熟悉十进制,特别是来自浮点数的转换。 - Drew Noakes


你写完711989.98f的那一刻就失去了精确度。

711989.98是小数。最后使用f,您要求编译器将其转换为float。在不失去精度的情况下无法完成此转换。

你可能想要的是小数d = 711989.98m。这不会失去精确度。


1
2018-04-07 18:23



你的例子只使用了一个双,对吗?对于不同的数字,它仍然会失去精确度。只需在末尾添加一个'm',然后将字面值设为小数。 - Carl G