gpt4 book ai didi

java - Java 整数类型原始类型是否在转换类型的 MAX_INT 处转换为 "capped"?

转载 作者:塔克拉玛干 更新时间:2023-11-03 03:37:34 27 4
gpt4 key购买 nike

我试图追踪一些非常奇怪的 Java 行为。我有一个涉及 double 的公式,但“保证”给出整数答案——具体来说,是一个无符号的 32 位整数(唉,Java 做得不好)。不幸的是,我的回答有时不正确。

最终我发现了这个问题,但对我来说这种行为仍然很奇怪:一个double直接转换为一个int似乎对于有符号整数,上限为 MAX_INT,而 double 转换为 longthen 转换为int 给出了预期的答案(-1;无符号 32 位整数的 MAX INT 表示为带符号的 32 位整数)。

我写了一个小测试程序:

public static void main(String[] args) {
// This is the Max Int for a 32-bit unsigned integer
double maxUIntAsDouble = 4294967295.00;
long maxUintFromDoubleAsLong = (long)maxUIntAsDouble;
long maxUintFromDoubleAsInt = (int)maxUIntAsDouble;
int formulaTest = (int) (maxUintFromDoubleAsLong * 1.0);
int testFormulaeWithDoubleCast = (int)((long) (maxUintFromDoubleAsLong * 1.0));
// This is a more-or-less random "big number"
long longUnderTest = 4123456789L;
// Max int for a 32-bit unsigned integer
long longUnderTest2 = 4294967295L;
int intFromLong = (int) longUnderTest;
int intFromLong2 = (int) longUnderTest2;
System.out.println("Long is: " + longUnderTest);
System.out.println("Translated to Int is:" + intFromLong);
System.out.println("Long 2 is: " + longUnderTest2);
System.out.println("Translated to Int is:" + intFromLong2);
System.out.println("Max UInt as Double: " + maxUIntAsDouble);
System.out.println("Max UInt from Double to Long: " + maxUintFromDoubleAsLong);
System.out.println("Max UInt from Double to Int: " + maxUintFromDoubleAsInt);
System.out.println("Formula test: " + formulaTest);
System.out.println("Formula Test with Double Cast: " + testFormulaeWithDoubleCast);
}

当我运行这个小程序时,我得到:

Long is: 4123456789
Translated to Int is:-171510507
Long 2 is: 4294967295
Translated to Int is:-1
Max UInt as Double: 4.294967295E9
Max UInt from Double to Long: 4294967295
Max UInt from Double to Int: 2147483647
// MAX INT for an unsigned int
Formula test: 2147483647
// Binary: all 1s, which is what I expected
Formula Test with Double Cast: -1

下面两行是我试图理解的。双重 Actor 给了我预期的“-1”;但是直接转换为 MAX_INT 提供了一个 32 位有符号整数。来自 C++ 背景,如果它给了我一个“奇数”而不是预期的 -1(又名“天真转换”),我会理解,但这让我感到困惑。

那么,接下来的问题是:这是 Java 中的“预期”行为吗(例如,任何直接转换为 intdouble 将被“限制”为 MAX_INT)?转换是否对任何意外类型执行此操作?例如,我希望 shortbyte 类似;但是将超大 double 值转换为 float 时的“预期行为”是什么?

谢谢!

最佳答案

这是预期的行为。请记住,Java 中没有原始的 unsigned long 或 int 类型,Java Language Specification (Java 7) 的 Narrowing primitive conversion (5.1.3) 声明将“太小或太大”的浮点值(无论是 double 还是浮点)转换为整数类型的 int 或 long 将使用的最小值或最大值有符号整数类型(强调我的):

A narrowing conversion of a floating-point number to an integral type T takes two steps:

  1. In the first step, the floating-point number is converted either to a long, if T is long, or to an int, if T is byte, short, char, or int, as follows:

    • If the floating-point number is NaN (§4.2.3), the result of the first step of the conversion is an int or long 0.
    • Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:

      • a. If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V.
      • b. Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.
    • Otherwise, one of the following two cases must be true:

      • a. The value must be too small (a negative value of large magnitude or negative infinity), and the result of the first step is the smallest representable value of type int or long.
      • b. The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int or long. *
  2. In the second step: * If T is int or long, the result of the conversion is the result of the first step. * If T is byte, char, or short, the result of the conversion is the result of a narrowing conversion to type T (§5.1.3) of the result of the first step.

Example 5.1.3-1. Narrowing Primitive Conversion

class Test {
public static void main(String[] args) {
float fmin = Float.NEGATIVE_INFINITY;
float fmax = Float.POSITIVE_INFINITY;
System.out.println("long: " + (long)fmin + ".." + (long)fmax);
System.out.println("int: " + (int)fmin + ".." + (int)fmax);
System.out.println("short: " + (short)fmin + ".." + (short)fmax);
System.out.println("char: " + (int)(char)fmin + ".." + (int)(char)fmax);
System.out.println("byte: " + (byte)fmin + ".." + (byte)fmax);
}
}

This program produces the output:

long: -9223372036854775808..9223372036854775807
int: -2147483648..2147483647
short: 0..-1
char: 0..65535
byte: 0..-1

The results for char, int, and long are unsurprising, producing the minimum and maximum representable values of the type.

The results for byte and short lose information about the sign and magnitude of the numeric values and also lose precision. The results can be understood by examining the low order bits of the minimum and maximum int. The minimum int is, in hexadecimal, 0x80000000, and the maximum int is 0x7fffffff. This explains the short results, which are the low 16 bits of these values, namely, 0x0000 and 0xffff; it explains the char results, which also are the low 16 bits of these values, namely, '\u0000' and '\uffff'; and it explains the byte results, which are the low 8 bits of these values, namely, 0x00 and 0xff.

第一种情况 int formulaTest = (int) (maxUintFromDoubleAsLong * 1.0); 因此通过乘法将 maxUintFromDoubleAsLong 提升为 double,然后将其转换为 int。由于该值太大而无法表示为有符号整数,因此该值变为 2147483647 (Integer.MAX_VALUE) 或 0x7FFFFFFF。

至于后一种情况:

A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.

因此 int testFormulaeWithDoubleCast = (int)((long) (maxUintFromDoubleAsLong * 1.0)); 首先将 maxUintFromDoubleAsLong 提升为 double,返回为 long(仍然适合),然后为 int。在最后一个转换中,多余的位被简单地丢弃,留下 0xFFFFFFFF,当被解释为有符号整数时它是 -1。

关于java - Java 整数类型原始类型是否在转换类型的 MAX_INT 处转换为 "capped"?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10641559/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com