奇怪的转换 double 到 int

Strange Conversion double to int

我最近在 ios swift 将 Double 转换为 Int 时遇到了一个小问题。

var myDoubleValue: Double = 10.2
var newInt = Int(myDoubleValue * 100) //1019

我将 10.2 乘以 100,但没有得到预期值 (1020),而是 1019...

但在大多数情况下工作正常,如下所示

var myDoubleValue: Double = 10.3
var newInt = Int(myDoubleValue * 100) //1030

我还用 Java 进一步测试了它,那里也有同样的问题..

double myDoubleValue = 10.2;
int myIntValue1 = (int)(myDoubleValue * 100); //1019

我可以通过在转换为 Int 之前执行 'round' 来解决这个问题...

var myDoubleValue: Double = 10.2
var newInt = Int(round(myDoubleValue * 100)) //1020

但是如果该值具有如下所示的小数点后 3 位,这会导致我不想要的结果,因为它当时正在四舍五入 (10.206 ---> 1021)

Java 回答

这是因为 doublefloat 类型和包装器在操作时不保证精确值。

在 Java 中,针对您要查找的内容推荐的成语是:

BigDecimal myDoubleValue = new BigDecimal("10.2");
int myInt = myDoubleValue.multiply(new BigDecimal("100")).intValue();
System.out.println(myInt);

输出

1020

这是 轮 up/truncation 错误 的结果。实际上,

  myDoubleValue = 10.2 

类似于

  myDoubleValue = 10.1999999999999

所以

 myDoubleValue * 100 = 1019.999999999

trimmedint 之后,你有 1019。更好的做法是 舍入 而不是 trim:

 double myDoubleValue = 10.2;
 int myIntValue1 = (int)(myDoubleValue * 100 + 0.5); // note "+ 0.5"
 System.out.println(myIntValue1);

您似乎想对少量错误进行舍入,但又想以其他方式进行舍入。

你可以做到

double d = 10.199999;
long l = (long) (d * 100 + 0.01); // l = 10.20

double d = 10.206;
long l = (long) (d * 100 + 0.01); // l = 10.20

一个显示的值就是那个,不是整个值,使用格式化可以看到更多的数字。 10.2 或 10.3 无法用 base2 浮点数准确表示,因此结果可能与预期略有不同。

这是一个说明正在发生的事情的例子:

var myDoubleValue1: Double = 10.2
print(String(format: "myDoubleValue1: %.17f", myDoubleValue1))
// myDoubleValue1: 10.19999999999999929

var myDoubleValue2: Double = 10.3
print(String(format: "myDoubleValue2: %.17f", myDoubleValue2))
// myDoubleValue2: 10.30000000000000071

请注意,10.2 转换为浮点数 Double 略低于 10.2,并且将被截断。

请注意,10.3 转换为浮点数 Double,略高于 10.3,并且 不会 被截断。

如果需要精确的十进制数学运算,例如在计算器中或处理金钱时,请使用 NSDecimalNumber