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

给我 333333333

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

给我 333333344

任何想法为什么?

4

3 回答 3

6

发生这种情况是因为Single没有足够的精度来存储您的完整号码。

Double具有更高的精度。

于 2013-10-24T17:03:37.990 回答
4

从文档中System.Single

所有浮点数都有有限数量的有效数字,这也决定了浮点值与实数近似的准确程度。Double 值具有最多 7 位十进制数字的精度,但内部维护最多 9 位数字。

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

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

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

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

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

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

于 2013-10-24T17:04:26.710 回答
4

浮点规范说浮点数的 32 位表示是

在此处输入图像描述

因此,可以在不损失(整数)精度的情况下表示的最大整数是 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 xxx = Convert.ToDouble(dr["NationalTotal"]);

我想向您推荐 http://floating-point-gui.de/ -“每个程序员都应该了解的浮点知识”。实际上有很多指南名称相似。如果你曾经偏离过只使用整数(大多数人会在他们的编程生涯的某个阶段),必读。

于 2013-10-24T17:16:04.287 回答