为什么要施放一个很大的长量int给我们带来一个奇怪的输出(Java)?

发布于 2025-01-26 22:02:52 字数 694 浏览 3 评论 0原文

我在爪哇练习一些铸件,并且面临着一个我在任何地方找不到任何答案的情况。有很多类似的问题带有答案,但是没有一个给我解释了这种特殊情况。

当我做类似

    long l = 165787121844687L;
    int i = (int) l;

    System.out.println("long: " + l);
    System.out.println("after casting to int: " + i);

输出的事情时,

long: 165787121844687
after casting to int: 1384219087

这个结果对我来说非常有趣。

我知道 long 的类型是64位整数, int 类型是32位整数。我还知道,当我们将较大类型的类型投入到较小的类型时,我们可能会丢失信息。而且我知道有一个非常有用的 Math.tointexact()方法。

但是,对此“ 1384219087 ”的解释是什么?数据丢失,但是为什么这个数字呢?如何“ 165787121844687 ”成为“ 1384219087 ”?为什么代码甚至编译?

就是这样。谢谢!

I was practicing some castings in Java and I faced a situation for which I couldn't find any answers, anywhere. There are a lot of similar questions with answers, but none gave me an explanation for this particular case.

When I do something like

    long l = 165787121844687L;
    int i = (int) l;

    System.out.println("long: " + l);
    System.out.println("after casting to int: " + i);

The output is

long: 165787121844687
after casting to int: 1384219087

This result is very intriguing for me.

I know that the type long is a 64-bit integer, and the type int is a 32-bit integer. I also know that when we cast a larger type to a smaller one, we can lose information. And I know that there is a Math.toIntExact() method that is quite useful.

But what's the explanation for this "1384219087" output? There was loss of data, but why this number? How "165787121844687" became "1384219087"? Why does the code even compile?

That's it. Thanks!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

絕版丫頭 2025-02-02 22:02:52

十六进制符号中的16578712184687L = 0000 96C8 5281 81CF

1384219087在六角符号中= 5281 81CF,

因此,铸件截断了预期的前32位。

                        32-bits 
                        deleted 
                       ▼▼▼▼ ▼▼▼▼
165_787_121_844_687L = 0000 96C8 5281 81CF  ➣  1_384_219_087
    64-bit long                  ▲▲▲▲ ▲▲▲▲      32-bit int 
                                  32-bits 
                                 remaining

165787121844687L in hex notation = 0000 96C8 5281 81CF

1384219087 in hex notation = 5281 81CF

So the cast truncated the top 32 bits as expected.

                        32-bits 
                        deleted 
                       ▼▼▼▼ ▼▼▼▼
165_787_121_844_687L = 0000 96C8 5281 81CF  ➣  1_384_219_087
    64-bit long                  ▲▲▲▲ ▲▲▲▲      32-bit int 
                                  32-bits 
                                 remaining
诠释孤独 2025-02-02 22:02:52

如果您将这两个数字转换为十六进制,您会

96C8528181CF
528181CF

看到这里发生了什么?

If you convert these two numbers to hexadecimal, you get

96C8528181CF
528181CF

See what's happened here?

倾城°AllureLove 2025-02-02 22:02:52

OldProgrammer的答案是正确的,应接受。这是一些其他信息,还有解决方法。

Java规格说这是如此

为什么代码甚至编译?

当您在Java中投放数字原始性时,您对结果负责,包括信息丢失的风险。

为什么?因为Java规格是这样说的。总是最好阅读文档。直觉编程是有风险的业务。

请参阅 java语言规范 href =“ https://docs.oracle.com/javase/specs/jls/se18/html/jls-5.html#jls-5.1.3” rel =“ nofollow noreferrer”> 5.1.3。缩小原始转换 。引用(强调我的):

狭窄的原始转换可能会丢失信息

将签名整数转换为整数t的狭窄转换,简单地丢弃了除n最低订单位以外的所有内容,其中n是代表T类型T的位数。除了可能关于数值的大小的信息丢失,这可能导致结果值的符号与输入值的符号不同。

数学#…精确…

想在long转换为简短,使用数学 精确的方法。如果操作溢出,则执行。您可以陷入此例外。

try 
{
   int i = Math.toIntExact( 165_787_121_844_687L ) ;  // Convert from a `long` to an `int`. 
} 
catch ( ArithmeticException e ) 
{ 
    // … handle conversion operation overflowing an `int` …
}

您会发现类似的数学#…精确…绝对值,加法,减少,增加,乘以,负和减法的方法。

The Answer by OldProgrammer is correct, and should be accepted. Here is some additional info, and a workaround.

Java spec says so

Why does the code even compile?

When you cast a numeric primitive in Java, you take responsibility for the result including the risk of information loss.

Why? Because the Java spec says so. Always best to read the documentation. Programming by intuition is risky business.

See the Java Language Specification, section 5.1.3. Narrowing Primitive Conversion. To quote (emphasis mine):

A narrowing primitive conversion may lose information

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.

Math#…Exact…

When you want to be alerted to data loss during conversion from a long to a short, use the Math methods for exactitude. If the operation overflows, an execution is thrown. You can trap for that exception.

try 
{
   int i = Math.toIntExact( 165_787_121_844_687L ) ;  // Convert from a `long` to an `int`. 
} 
catch ( ArithmeticException e ) 
{ 
    // … handle conversion operation overflowing an `int` …
}

You will find similar Math#…Exact… methods for absolute value, addition, decrementing, incrementing, multiplying, negating, and subtraction.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文