1. 首页
  2. 后端

Float.MAX_VALUE + 1 = Float.MAX_VALUE??

  Float.MAX\_VALUE + 1 = Float.MAX\_VALUE??

=========================================

前置:JAVA数据类型基础知识

===============

数据类型

image.png

数据类型定义与取值范围

image.png

位溢出

在 Java 中,数据类型有固定的大小,并且它们的整数表示是使用补码(two’s complement)形式。这种表示形式对整数进行加法和减法时会导致溢出(overflow)。溢出时,结果不会引发错误或异常,而是以一种特定的方式“环绕”到最小或最大可能值。

正题

好了,有了上面的知识,便可以开始我们今天的正题了,先来看看下图
image.png
乍一看,是不是毫无规律,IntegerLong加完1后变MIN_VALUEShort却没有位溢出变MIN_VALUE,接下来的FloatDouble加1后并没有变MIN_VALUE,也没有变化(当然这里加的数太小,不足以论证没有变化,我们下文再详解)

Integer

Integer的位溢相信大家都熟悉,但这里还是不厌其烦的解释一下

Integer.MAX_VALUE2147483647,这是一个 32 位有符号整数的最大值。二进制表示如下:

01111111 11111111 11111111 11111111

当 +1 时,发生溢出,导致最左边的一位(符号位)变为 1:

10000000 00000000 00000000 00000000

在补码表示中,这个值是 -2147483648,即 Integer.MIN_VALUE。所以 Integer.MAX_VALUE + 1 变成了负数 -2147483648

但是,如果明确指明’1’类型Long(即’1L’),结果则会变为2147483648

image.png

Long

LongInteger同理

Long.MAX_VALUE9223372036854775807,这是一个 64 位有符号整数的最大值。其二进制表示如下:

01111111 11111111 11111111 11111111 11111111 11111111 11111111 11111111

当在这个值上加 1 时,发生溢出,导致最左边的一位(符号位)变为 1:

10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000

在补码表示中,这个值是 -9223372036854775808,即 Long.MIN_VALUE。所以 Long.MAX_VALUE + 1 变成了负数 -9223372036854775808

Short

Short.MAX_VALUE32767,这是一个 16 位有符号整数的最大值。二进制表示如下:

01111111 11111111

当你加 1 时,发生溢出:

10000000 00000000

在补码表示中,这个值是 -32768,即 Short.MIN_VALUE

然而,在 Java 中,short 类型的操作会自动提升为 int 类型进行计算,因此 Short.MAX_VALUE + 1 实际上是一个 int 计算:

32767 + 1 = 32768

这个结果在 int 类型范围内,所以不会发生溢出,结果是正数 32768

Float

Float.MAX_VALUE 是 3.4028235e+38,这是最大的正浮点数

Float.MIN_VALUE 是 1.4e-45,这是最小的正浮点数(靠近 0,但不是 0,是不是很容易被上面带坏以为是负值🤐)

浮点数的溢出行为

为什么 Float.MAX_VALUE + 1 不会变成 Float.MIN_VALUE

Float.MAX_VALUE 加任何数时,由于 Float.MAX_VALUE 已经是最大值,结果会超出 float 类型的表示范围。因此,结果将是正无穷大(Float.POSITIVE_INFINITY),而不是 Float.MIN_VALUE

  • Float.MIN_VALUE 是接近 0 的最小正数,而不是表示溢出到最小数的特殊值。
  • 浮点数运算遵循 IEEE 754 标准,正溢出会导致结果变为无穷大,而不是循环到最小值。

image.png

当浮点数超过其可表示的范围时,会发生溢出

  • 正溢出:当一个浮点数超过 Float.MAX_VALUE,结果将是正无穷大(Float.POSITIVE_INFINITY)。
  • 负溢出:当一个负浮点数的绝对值超过 Float.MAX_VALUE 的负值,结果将是负无穷大(Float.NEGATIVE_INFINITY)。

image.png

Double

DoubleFloat同理

Double.MAX_VALUE 是 1.7976931348623157e+308

Double.MIN_VALUE 是 4.9e-324

双精度浮点数的溢出行为

image.png

正溢出与负溢出

image.png

题外:Java 中的数据类型转型上升

什么是数据类型转型上升?

数据类型转型上升(Numeric Promotion)指的是在算术运算中,较小的数据类型会自动提升到较大或更通用的数据类型。Java 的数值提升规则如下:

  1. 整型提升:在算术运算中,byteshortchar 会被提升为 int 类型。如果一个操作数是 long,另一个操作数也会提升为 long
  2. 浮点提升:如果一个操作数是 float,另一个操作数会提升为 float。如果一个操作数是 double,另一个操作数会提升为 double

为什么会有数据类型转型上升?

在 Java 编程中,数据类型的转型(或称类型提升)是一个常见且重要的概念。理解它的原理和应用对于编写高效且正确的代码至关重要。在这篇文章中,我们将深入探讨 Java 中的数据类型转型上升,解释其背后的原理,并通过示例展示其实际应用。
这种自动提升机制主要是为了以下原因:

  1. 避免溢出和信息丢失:较小的数据类型在进行算术运算时,如果不提升为 int 或更高类型,可能会由于其有限的表示范围而导致溢出或信息丢失。例如,byte 类型的范围是 -128 到 127,如果两个 byte 值相加结果超出这个范围,会导致错误的结果。
  2. 简化处理逻辑:如果所有算术运算都在 int 类型及以上进行,可以简化 JVM 的实现和优化逻辑,从而提高运行效率和代码的可移植性。

不同数据类型在算术运算中的提升行为:

public class NumericPromotionExample {
    public static void main(String[] args) {
        short a = 32767;  // Short.MAX_VALUE
        short b = 1;
        int result = a + b;
        System.out.println("Result: " + result);  // 输出 "Result: 32768"
    }
}

在上面的代码中:

  1. ab 都是 short 类型。
  2. a + b 运算中,ab 都会被自动提升为 int 类型。
  3. 结果 32768int 类型,因为 short 类型无法表示 32768(超出了 short 的范围)。

int 类型的特殊情况

在 Java 中,int 类型是 32 位的整数类型,已经是 Java 中最常用的整数类型之一。为了保持性能和简化处理,int 类型在算术运算中不会自动提升到更高的类型(如 longdouble),除非有混合类型的操作数。例如:

  • 如果一个操作数是 long,那么 int 操作数会被提升为 long
  • 如果一个操作数是 float,那么 int 操作数会被提升为 float
  • 如果一个操作数是 double,那么 int 操作数会被提升为 double

int 在不同操作数类型中的提升行为:

public class NumericPromotionExample {
    public static void main(String[] args) {
        int intVal = 2147483647; // Integer.MAX_VALUE
        long longVal = 10L;
        float floatVal = 1.5f;
        double doubleVal = 2.5;

        // int + long -> long
        long result1 = intVal + longVal; // 自动提升为 long
        System.out.println("int + long -> long: " + result1);

        // int + float -> float
        float result2 = intVal + floatVal; // 自动提升为 float
        System.out.println("int + float -> float: " + result2);

        // int + double -> double
        double result3 = intVal + doubleVal; // 自动提升为 double
        System.out.println("int + double -> double: " + result3);

        // 溢出示例
        int overflowResult = intVal + 1; // 不会提升,导致溢出
        System.out.println("Integer.MAX_VALUE + 1: " + overflow

原文链接: https://juejin.cn/post/7374045077452423195

文章收集整理于网络,请勿商用,仅供个人学习使用,如有侵权,请联系作者删除,如若转载,请注明出处:http://www.cxyroad.com/17296.html

QR code