C# 将对象转换为长对象
我有以下功能:C# 将对象转换为长对象,c#,C#,我有以下功能: public virtual long AsLong(object originalValue,long defaultValue) { double buffer = defaultValue; if (originalValue != null) { double result; var readValueIsconverted = double.TryParse(
public virtual long AsLong(object originalValue,long defaultValue)
{
double buffer = defaultValue;
if (originalValue != null)
{
double result;
var readValueIsconverted = double.TryParse(originalValue.ToString(), out result);
if (readValueIsconverted)
buffer = result;
}
var roundedValue = Math.Round(buffer, 0);
var convertedValue = (long) roundedValue;
return convertedValue;
}
我已经使用了double以允许14.4的转换!
我有以下失败的测试:
[Fact]
public void CanConvertLongMaxValue()
{
var cellValue = new Converter();
const long longValue = 0x7FFFFFFFFFFFFFFF;
var result = cellValue.AsLong(longValue, 12);
Assert.Equal(longValue, result);
}
我已经跟踪了代码,roundedValue为正,但convertedValue为负。那么问题出在哪里呢?问题是,您试图在一个双精度
中保存一个包含19个有效数字(十进制)的整数值,而该双精度
因此,不可能在double
中准确地表示值。显然,舍入会在转换为long时导致值溢出,使其成为负值
您可以这样确认:
var convertedValue = checked((long)roundedValue);
如果您一定要处理这种情况,我建议您使用double而不是double,或者在小数点处拆分字符串(或您的区域设置中使用的任何内容),并以这种方式处理舍入。如果提供的参数在第一位是long
,您应该检查:
public virtual long AsLong(object originalValue,long defaultValue)
{
if(originalValue.GetType() == typeof(long))
return (long) originalValue;
double buffer = defaultValue;
...
}
否则,您可能会丢失有关long
到double
转换的一些信息。检查原始值的类型。它的编译时类型是object
,但运行时的实际类型是什么?如果是盒式数字类型,则无需调用.ToString()
后跟TryParse
。最好直接取消装箱到正确的类型(特别是如果它始终是相同的运行时类型),然后在必要时转换为另一个数字类型
如果通过double
发送包含许多数字的long
,如0x7FFFFFFFFFFFFFFF
,它与long.MaxValue
相同,请注意long
比double
具有大约10位的精度。从技术上讲,这是因为双精度
使用11位作为指数,但不必存储最高有效位
当值为long.MaxValue
时,double
的精度会发生变化,因为当我们通过2的幂时,指数会上升1double
值正好低于long。MaxValue
的精度为1024。这意味着只能表示1024的整数倍。毫不奇怪,double
值正好在long.MaxValue
之上,其精度为2048。当然,整型long
的精度总是正好为1
下面是三个最接近的double
长long.MaxValue
:
9.22337203685477'27'36 E+18
9.22337203685477'37'60 E+18
9.22337203685477'47'84 E+18
---
9.22337203685477'58'08 E+18 <-- two to the 63rd power
9.22337203685477'78'56 E+18
9.22337203685477'99'04 E+18
9.22337203685477'27'36 E+18
9.22337203685477'37'60东+18
9.22337203685477'47'84东+18
---
9.22337203685477'58'08 E+18为什么解析为double以返回long?请参见。。或者..因为可以将示例13.4作为参数传递。如果我对缓冲区使用了long,我就错过了这种可能性。long roundedValue=(long)Math.Round(myDoubleValue,0)@我不明白。我也做了同样的事情。不是吗?