Unity中C# float转int异常:乘法结果被意外向下取整?
float转int时出现向下取整偏差的原因分析
问题现象
在Unity的C#开发中遇到float转int的异常:
- 计算
x * 1.05时,结果等同于x * 1 - 计算
x * 1.1时,结果等同于x * 1.05
Unity环境测试代码
using System; public class Example { public static void Main() { int gainAmount = 20; float _gainAmountModifier = 1.05f; gainAmount = (int)(gainAmount * _gainAmountModifier); Debug.Log(_gainAmountModifier); Debug.Log(gainAmount); } }
输出:
1.05 20
C#沙箱测试代码
using System; public class Example { public static void Main() { int var_int = 100; float var_f = var_int; var_f = var_f * 1.05f; var_int = (int)var_f; Console.WriteLine(var_f); Console.Write(var_int); } }
输出:
105 104
核心原因
问题出在float类型的精度限制:
- 十进制的1.05无法用二进制浮点数精确存储,实际在内存中存储的是一个略小于1.05的近似值(比如
1.0499999523162842)。 - 当计算
20 * 1.05f时,实际结果是20.999999046325684,直接用(int)强制转换会截断所有小数部分,只保留整数位20。 - 在沙箱测试中,
100 * 1.05f的实际结果是104.99999237060547,Console.WriteLine会对这个值做四舍五入显示为105,但(int)转换依然截断小数得到104,这就造成了显示值和实际转换结果的矛盾。
解决方案
针对这类需要精确数值转换的场景,推荐以下几种方式:
- 使用四舍五入转换:在Unity中用
Mathf.RoundToInt(),普通C#环境用Math.Round(),会根据小数部分的值自动取整:// Unity示例 gainAmount = Mathf.RoundToInt(gainAmount * _gainAmountModifier); // 普通C#示例 var_int = (int)Math.Round(var_f); - 使用decimal类型计算:decimal的精度更高,适合处理货币、百分比这类需要精确十进制运算的场景:
int var_int = 100; decimal var_d = var_int; var_d = var_d * 1.05m; var_int = (int)var_d; - 手动补偏后截断:如果需要向下取整但避免精度误差,可以先给结果加一个极小的偏移值(比如
0.0001f)再转换:gainAmount = (int)(gainAmount * _gainAmountModifier + 0.0001f);
内容的提问来源于stack exchange,提问作者Sid Chou
相关产品推荐
相关产品推荐

