48

你好,我从 DataSet 中的 DataTable 中提取了一个 DataRow。我正在访问在 SQL 中定义为浮点数据类型的列。我正在尝试将该值分配给局部变量(c#float 数据类型),但得到一个 InvalidCastExecption

DataRow exercise = _exerciseDataSet.Exercise.FindByExerciseID(65);
_AccelLimit = (float)exercise["DefaultAccelLimit"];  

现在,玩弄这个我确实让它工作了,但它没有任何意义,而且感觉不对。

_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];

谁能解释我在这里缺少什么?

4

6 回答 6

84

根据SQLDbType 的文档, SQL 浮点数是双精度数。

于 2008-09-23T17:41:20.340 回答
27

SQL 中的浮点数是 CLR (C#/VB) 中的Double。MSDN 上有一个带有 CLR 等效项的 SQL 数据类型表。

于 2008-09-23T17:49:43.687 回答
4

如果您计划对数据执行数学计算,通常您永远不会希望在 SQL Server(或真实)中使用浮点数,因为它是不精确的数据类型,并且会引入计算错误。如果您需要精度,请改用十进制数据类型。

于 2008-09-23T18:17:12.560 回答
2

Microsoft SQL Server 中的浮点数相当于 C# 中的 Double。原因是浮点数只能逼近十进制数,浮点数的精度决定了该数逼近十进制数的准确程度。Double 类型表示双精度 64 位浮点数,其值范围从负 1.79769313486232e308 到正 1.79769313486232e308,以及正或负零、PositiveInfinity、NegativeInfinity 和 Not-a-Number (NaN)。

于 2008-09-23T18:05:48.547 回答
0

我认为这里已经回答了主要问题,但我觉得有必要为问题的部分添加一些内容,说明这很有效。

_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];

这个“有效”的原因和它“感觉不对”的原因是你正在通过第二次强制转换(左边的那个)将双精度降级为浮点数,所以你正在失去精度并有效地告诉编译器它可以截断返回的值。

换句话说,这行说明...获取一个对象(在这种情况下恰好包含一个双精度)将对象转换为双精度(丢失所有对象包装)将双精度转换为浮点数(丢失所有精细精度双)

例如,如果值是 0.0124022806089461 并且您执行上述操作,那么 AccelLimit 的值将是 0.01240228

因为这是 c# 中的浮点数可以从双精度值中获得的程度。这是一件危险的事情,我很确定它也是截断而不是四舍五入,但有人可能想确认这一点,因为我不确定。

于 2015-10-08T13:28:51.733 回答
0

它“感觉不对”的原因是因为 C# 使用相同的语法进行拆箱强制转换,这是两个非常不同的东西。exercise["DefaultAccelLimit"]包含一个双精度值,装箱为一个对象。(double)需要将对象拆箱回双。前面(float)的然后双精度转换为浮点值。C# 不允许在同一操作中进行装箱和强制转换,因此您必须先取消装箱,然后再进行强制转换。

即使演员表是非破坏性的,情况也是如此。如果一个浮点数被装箱为一个你想转换成双精度的对象,你会这样做(double)(float)object_var

于 2015-10-14T18:58:17.367 回答