var x = dr["NationalTotal"].ToString();
给了我333333333
var xxx = Convert.ToSingle(dr["NationalTotal"].ToString());
给了我333333344
任何想法为什么?
答案 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位表示为
因此,可以在不损失(整数)精度的情况下表示的最大整数是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/ - “每个程序员应该了解浮点数”。实际上有很多指南都有相似的名字。如果你偏离使用整数(大多数人会在他们的编程生涯中的某些时候),必要的阅读。