c#string to float conversion无效?

时间:2013-10-24 17:01:19

标签: c# floating-point floating-accuracy type-conversion

var x = dr["NationalTotal"].ToString();

给了我333333333

var xxx = Convert.ToSingle(dr["NationalTotal"].ToString());

给了我333333344

任何想法为什么?

3 个答案:

答案 0 :(得分:6)

这是因为Single没有足够的精确度来存储您的完整号码。

Double具有更高的精确度。

答案 1 :(得分:4)

来自System.Single的文档:

  

所有浮点数的有效位数都有限,这也决定了浮点值接近实数的准确程度。 Double值最多包含7个十进制数字的精度,但内部最多保留9位数。

实际上意味着 Single而不是Double,但关键在于您尝试将其用于9位有效数字,并且不能保证可用。无需任何解析,您可以非常轻松地看到它:

float f = 333333333f;
Console.WriteLine("{0:r", f); // Prints 333333344

(“r”是“往返”格式说明符。)

换句话说,与精确十进制值333333333最接近的float值为333333344。

如果您使用Double代替,那可能会保留所有数字,但这并不意味着它必然是正确的方法。这取决于价值。 实际上总是一个整数吗?也许你应该使用long。它是非整数,但是财务数据(或其他一些“人为”价值)?如果是,请考虑使用decimal

另外,为什么你必须将它转换为字符串并解析它?什么是dr["NationalTotal"]的执行时间类型?您可能只需要强制转换 - 避免在不需要的地方使用字符串转换。

答案 2 :(得分:4)

浮点规范表明浮点数的32位表示为

enter image description here

因此,可以在不损失(整数)精度的情况下表示的最大整数是16777216(0x1000000)。一个简单的测试程序,以说服你这样做:

#include <stdio.h>

int main(void) {
  float x;
  unsigned long j;
  j = 0x00FFFFFC;
  int i;
  x = j;
  for(i=0; i<10;i++)  printf("%ld + %d = %f\n", j, i, x+i);
}

输出:

16777212 + 0 = 16777212.000000
16777212 + 1 = 16777213.000000
16777212 + 2 = 16777214.000000
16777212 + 3 = 16777215.000000
16777212 + 4 = 16777216.000000
16777212 + 5 = 16777216.000000  <<< from here on, adding one more doesn't give the right answer
16777212 + 6 = 16777218.000000
16777212 + 7 = 16777220.000000
16777212 + 8 = 16777220.000000
16777212 + 9 = 16777220.000000

编辑根据问题背后的评论,我们慢慢收敛到你有两个问题,而不是一个问题。

第一个:“为什么会发生这种情况?”上面的回答。单个浮点数无法准确表示333333333,因此您可以获得最接近的可表示值,即333333344

第二个:“我如何解决?”最初由我在评论中回答 - 我将在此重申我的答案:

您的数据库浮点数通常不是单精度 - 事实上,默认情况下它是双精度。因此,您可以通过将字符串转换为double并将其分配给双精度变量来解决您的问题:

double xxx = Convert.ToDouble(dr["NationalTotal"]);

我想请你参考http://floating-point-gui.de/ - “每个程序员应该了解浮点数”。实际上有很多指南都有相似的名字。如果你偏离使用整数(大多数人会在他们的编程生涯中的某些时候),必要的阅读。