string[] strArray = new string[10] { "21.65", "30.90", "20.42", "10.00", "14.87", "72.19", "36.00", "45.11", "18.66", "22.22" };
float temp = 0.0f;
Int32 resConvert = 0;
Int32 resCast = 0;
for (int i = 0; i < strArray.Length; i++)
{
float.TryParse(strArray[i], out temp);
resConvert = Convert.ToInt32(temp * 100);
resCast = (Int32)(temp * 100);
Console.WriteLine("Convert: " + resConvert + " ExplCast: " + resCast);
}
并且:
Convert: 2165 ExplCast: 2164 // ??
Convert: 3090 ExplCast: 3089 // ??
Convert: 2042 ExplCast: 2042
Convert: 1000 ExplCast: 1000
Convert: 1487 ExplCast: 1486 //??
Convert: 7219 ExplCast: 7219
Convert: 3600 ExplCast: 3600
Convert: 4511 ExplCast: 4511
Convert: 1866 ExplCast: 1865 //??
Convert: 2222 ExplCast: 2221 //??
为什么在进行Explicit Cast时值有时会有所不同,但并非总是如此。 有什么原因吗?
答案 0 :(得分:9)
举一个例子,float
格式的21.65实际上由21.6499999这样的数字表示。 Convert.ToInt32
将数字四舍五入到最接近的整数,产生21.65,而显式转换(Int32)
只是截断(向零舍入),因此得到21.64。
如果您希望浮点数在计算机中的显示方式与打印出来的方式相同,请使用decimal
代替float
或double
。
答案 1 :(得分:4)
Convert.ToInt32
rounds to the nearest integer,直接投射会截断数字。
因此,如果由于浮点不精确而使用2165.99999whatever
而不是2165.0
,则直接转换会在浮点之后截断所有值,而Convert.ToInt32
则转向最接近整数。
例:
22.22f * 100.0f
会产生类似2221.99993133544921875
的内容
因此,Convert.ToInt32
会将向上舍入到预期值2222
,而广播会将其截断为2221
。
45.11f * 100.0f
导致大约4511.00006103515625
,
其中Convert.ToInt32
轮次向下,结果为4511
,与直接投放时的结果相同。
答案 2 :(得分:2)
以下来自Botz3000的答案,来自MSDN的Relevent部分:
Convert.ToInt32 Method (Single)
返回值类型:System.Int32值,四舍五入到最接近的32位 有符号整数。如果值是两个整数之间的中间值,那么 偶数返回;也就是说,4.5转换为4,而5.5是 转换为6。
Explicit Numeric Conversions Table
•从double或float值转换为整数类型时, 该值向零舍入为最接近的整数值。如果 结果积分值超出目的地范围 值,结果取决于溢出检查上下文。在一个 检查上下文,在未选中时抛出OverflowException 上下文,结果是目标类型的未指定值。
答案 3 :(得分:1)
我认为您会发现问题是由浮点精度不准确造成的,特别是使用float
。使用decimal
时,您会发现问题消失。这里对decimal和double(和float)之间的差异有一个非常好的答案:decimal vs double! - Which one should I use and when?
答案 4 :(得分:1)
调用Convert.ToInt32就像调用:
(int) Math.Round(floatValue, 0);
直接投射就像打电话
(int) Math.Floor(float);
Floor总是为您提供小于或等于您在参数中提供的值的值。浮点表示不是“精确的”。所以21.65可能表示为21.649999或类似,因为没有足够的精度。
所以: 21.65 * 100 = 2164.9999 对此值进行地板应该为您提供一个小于或等于2164.9的整数...即:2164
另一方面,舍入2164.99会给你:2165
你可以在这里看到效果:
Console.WriteLine(Math.Round(21.65f*100)); //2165
Console.WriteLine(Math.Floor(21.65f*100)); //2164
使用双精度而不是浮点数(更精确,但仍然不是无限):
Console.WriteLine(Math.Round(21.65d*100)); //2165
Console.WriteLine(Math.Floor(21.65d*100)); //2165