我正在尝试将 2147483648 的双精度值转换为整数,键入后,我得到的输出为 2147483647,数字减少了 1。我知道这是由于溢出而发生的,但是有没有办法可以在不损失精度的情况下将其转换为 int 类型?
如前面的答案所述,您可以使用long
基元数据类型或BigInteger
引用类型。使用整型数据类型而不是浮点型可以更好地精确表示整数。
作为旁注,从Java SE 8开始,可以使用Integer
类将int用于无符号算术。根据 Oracle 文档 - "使用 Integer 类将 int 数据类型用作无符号整数"。无符号整数的最大值大于 int。这个问题可能很有用:在 Java 中声明一个无符号的 int。
这是我的第一个答案,希望你能解决你的问题!:)
我可以想到 2 个选项。
长
与int
不同, 是 32 位有符号整数数据类型,long
是 64 位有符号整数数据类型。这意味着它可以存储的最大值是9223372036854775807
.2147483648,您尝试存储的数字完全在该范围内。
大整数
这是一个引用类型,表示"不可变的任意精度整数"。您可以通过执行以下操作来创建表示2147483648的BigInteger
实例
new BigInteger("2147483648")
在此处了解更多信息:https://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html
最大值
最大整数(如 Integer 类中由static final int MAX_VALUE
表示)为 2^31-1 (2,147,483,647)。此值是最大整数,因为它是最大的 32 位有符号整数。
最大双精度,如 Double 类中由static final int MAX_VALUE
表示的那样,是 (2-2^(-52))(2^1023)。双精度数据类型遵循双精度 64 位 IEEE 754 浮点格式来表示各种动态数值。
缩小基元转换
在您的观察中,您有一个值为 2,147,483,648 的双精度值,您尝试通过类型转换将其转换为整数。
double d = 2147483648;
int i = (int) d;
基元类型之间的强制转换允许您将一个基元类型的值转换为另一个基元类型的值。从双精度转换为整数称为窄基元转换,其中您:
"可能会丢失有关数值总体量级的信息,还可能丢失精度和范围。
浮点数到 int 的缩小转换如下所示:
- 如果浮点数为 NaN,则结果为 int 为 0。 否则,如果浮点数
- 不是无穷大,则浮点数将舍入为整数值 V,并使用 IEEE 754 舍入到零模式向零舍入。如果此整数值可以表示为 int,则结果为 V。
- 否则,必须满足以下两种情况之一:a。该值必须太小,结果是 int 或 b 类型的最小可表示值。该值必须太大,结果是 int 类型的最大可表示值。
当双精度值的整数值大于 Integer.MAX_VALUE 时,为了允许表示为整数,使用 Integer.MAX_VALUE 的值。
避免损失
为了避免精度损失,您需要强制转换为基元类型或数值对象,其中最大值大于 2147483648(并且分辨率允许保持精度)。
长基元类型的最大值为 2^63-1 (9.223372e+18),如果要在数字整数空间中使用数字,这将是一个不错的选择。请注意,虽然 Long.MAX_VALUE 非常大,但由于浮点格式,Double.MAX_VALUE 要大得多。
double d = 2147483648;
long i = (long) d;
从double
转换为int
将失去大于Integer.MAX_VALUE
或小于Integer.MIN_VALUE
的数字的精度。 无法将该范围之外的数字表示为int
。 这在数学上是不可能的。
从double
转换为long
也会失去精度。 这将发生在Long.MIN_VALUE
到Long.MAX_VALUE
之外的所有整数。 但第二个问题是double
本身无法表示该范围内的所有整数......所以在转换1之前会有精度损失。
道德:
如果需要精确表示整数,请不要使用浮点数。 使用积分类型(byte
、short
、char
、int
或long
)...或BigInteger
.
1 -double
是一个 64 位 IEE 浮点数,具有 52 位精度和一个符号位。 相比之下,long
具有 64 位精度(包括符号)。