为什么 SQL 浮点数与 C# 浮点数不同
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/122523/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Why is a SQL float different from a C# float
提问by Keith Sirmons
Howdy, I have a DataRow pulled out of a DataTable from a DataSet. I am accessing a column that is defined in SQL as a float datatype. I am trying to assign that value to a local variable (c# float datatype) but am getting an InvalidCastExecption
你好,我从数据集中的数据表中提取了一个数据行。我正在访问在 SQL 中定义为浮点数据类型的列。我正在尝试将该值分配给一个局部变量(c# float 数据类型),但我得到了一个 InvalidCastExecption
DataRow exercise = _exerciseDataSet.Exercise.FindByExerciseID(65);
_AccelLimit = (float)exercise["DefaultAccelLimit"];
Now, playing around with this I did make it work but it did not make any sense and it didn't feel right.
现在,玩这个我确实让它工作了,但它没有任何意义,而且感觉不对。
_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];
Can anyone explain what I am missing here?
谁能解释我在这里缺少什么?
采纳答案by Austin Salonen
A SQL float is a double according to the documentation for SQLDbType.
根据SQLDbType 的文档,SQL 浮点数是双精度值。
回答by bdukes
A float in SQL is a Doublein the CLR (C#/VB). There's a table of SQL data types with the CLR equivalentson MSDN.
SQL 中的浮点数是CLR (C#/VB) 中的双精度数。MSDN 上有一个 SQL 数据类型表和 CLR 等效项。
回答by pdavis
The float in Microsoft SQL Server is equivalent to a Double in C#. The reason for this is that a floating-point number can only approximate a decimal number, the precisionof a floating-point number determines how accurately that number approximatesa decimal number. The Double type represents a double-precision 64-bit floating-point number with values ranging from negative 1.79769313486232e308 to positive 1.79769313486232e308, as well as positive or negative zero, PositiveInfinity, NegativeInfinity, and Not-a-Number (NaN).
Microsoft SQL Server 中的 float 等效于 C# 中的 Double。这样做的原因是浮点数只能近似十进制数,浮点数的精度决定了该数字近似十进制数的准确程度。Double 类型表示双精度 64 位浮点数,其值范围从负 1.79769313486232e308 到正 1.79769313486232e308,以及正或负零、PositiveInfinity、NegativeInfinity 和 Not-a-Number (NaN)。
回答by HLGEM
And normally you would never want to use float in SQL Server (or real) if you plan to perform math calculations on the data as it is an inexact datatype and it will introduce calculation errors. Use a decimal datatype instead if you need precision.
如果您计划对数据执行数学计算,通常您永远不会希望在 SQL Server(或实数)中使用浮点数,因为它是一种不精确的数据类型,并且会引入计算错误。如果需要精度,请改用十进制数据类型。
回答by David Bridge
I think the main question has been answered here but I feel compelled to add something for the section of the question that states that this works.
我认为主要问题已在此处得到解答,但我觉得有必要为该问题的部分添加一些内容,说明这是有效的。
_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];
_AccelLimit = (float)(double)exercise["DefaultAccelLimit"];
The reason this "works" and the reason it "doesn't feel right" is that you are downgrading the double to a float by the second cast (the one on the left) so you are losing precision and effectively telling the compiler that it is ok to truncate the value returned.
这“有效”的原因以及它“感觉不对”的原因是您通过第二次强制转换(左侧的那个)将 double 降级为浮点数,因此您正在失去精度并有效地告诉编译器它可以截断返回的值。
In words this line states... Get an object (that happens to hold a double in this case) Cast the object in to a double (losing all the object wrapping) Cast the double in to a float (losing all the fine precision of a double)
换句话说,这条线声明......获取一个对象(在这种情况下碰巧持有一个双精度数)将对象转换为双精度数(失去所有对象包装)将双精度数转换为浮点数(失去所有精度双)
e.g. If the value is say 0.0124022806089461 and you do the above then the value of AccelLimit will be 0.01240228
例如,如果值是 0.0124022806089461 并且您执行上述操作,则 AccelLimit 的值将为 0.01240228
as that is the extent of what a float in c# can get from the double value. Its a dangerous thing to do and I am pretty sure its a truncation too rather than a rounding but someone may want to confirm this as I am not sure.
因为这是 c# 中的浮点数可以从双精度值中获得的范围。这是一件危险的事情,我很确定它也是截断而不是四舍五入,但有人可能想确认这一点,因为我不确定。
回答by dubrowgn
The reason it "doesn't feel right" is because C# uses the same syntax for unboxingand for casting, which are two very different things. exercise["DefaultAccelLimit"]
contains a double value, boxed as an object. (double)
is required to unboxthe object back into a double. The (float)
in front of that then caststhe double to a float value. C# does not allow boxing and casting in the same operation, so you must unbox, then cast.
它“感觉不对”的原因是因为 C# 对拆箱和强制转换使用相同的语法,这是两个非常不同的事情。exercise["DefaultAccelLimit"]
包含一个 double 值,装箱为一个对象。(double)
需要将对象重新装箱为双。在(float)
前面那个然后投射双为浮点值。C# 不允许在同一操作中装箱和强制转换,因此您必须先拆箱,然后再转换。
The same is true even if the cast is nondestructive. If a float was boxed as an object that you wanted to cast into a double, you would do it like so: (double)(float)object_var
.
即使演员表是非破坏性的,也是如此。如果浴液盒装作为一个对象,你想投成一个双,你会做它像这样:(double)(float)object_var
。