簡體   English   中英

Java Float和Double數據類型中的上溢和下溢

[英]Overflow and Underflow in Java Float and Double Data Types

我創建了以下代碼來測試Float和Double Java數字數據類型的下溢和上溢:

// Float Overflow & Underflow
float floatTest = Float.MAX_VALUE;
floatTest++;
out.println("Float Overflow: " + Float.MAX_VALUE + " + 1 = " + floatTest);
floatTest = Float.MIN_VALUE;
floatTest--;
out.println("Float Underflow: " + Float.MIN_VALUE + " - 1 = " + floatTest);
out.println("");

// Double Overflow & Underflow
double doubleTest = Double.MAX_VALUE;
doubleTest++;
out.println("Double Overflow: " + Double.MAX_VALUE + " + 1 = " + doubleTest);
doubleTest = Double.MIN_VALUE;
doubleTest--;
out.println("Double Underflow: " + Double.MIN_VALUE + " - 1 = " + doubleTest);
out.println("");

有人可以解釋一下我在結果中看到的怪異值: 在此處輸入圖片說明

當我用byte,short,int和long做類似的測試(下面的代碼)時:

// BYTE Overflow & Underflow
byte byteTest = Byte.MAX_VALUE;
byteTest++;
out.println("Byte Overflow: " + Byte.MAX_VALUE + " + 1 = " + byteTest);
byteTest = Byte.MIN_VALUE;
byteTest--;
out.println("Byte Underflow: " + Byte.MIN_VALUE + " - 1 = " + byteTest);
out.println("");

// SHORT Overflow & Underflow
short shortTest = Short.MAX_VALUE;
shortTest++;
out.println("Short Overflow: " + Short.MAX_VALUE + " + 1 = " + shortTest);
shortTest = Short.MIN_VALUE;
shortTest--;
out.println("Short Underflow: " + Short.MIN_VALUE + " - 1 = " + shortTest);
out.println("");

// INTEGER Overflow & Underflow
int intTest = Integer.MAX_VALUE;
intTest++;
out.println("Integer Overflow: " + Integer.MAX_VALUE + " + 1 = " + intTest);
intTest = Integer.MIN_VALUE;
intTest--;
out.println("Integer Underflow: " + Integer.MIN_VALUE + " - 1 = " + intTest);
out.println("");

// LONG Overflow & Underflow
long longTest = Long.MAX_VALUE;
longTest++;
out.println("Long Overflow: " + Long.MAX_VALUE + " + 1 = " + longTest);
longTest = Long.MIN_VALUE;
longTest--;
out.println("Long Underflow: " + Long.MIN_VALUE + " - 1 = " + longTest);
out.println("");

結果看起來像預期的那樣:

在此處輸入圖片說明

有人可以解釋Java float和double中的上溢和下溢嗎,為什么我會看到上述結果?

浮點溢出

Double.MAX_VALUEFloat.MAX_VALUE 1不能代表足夠的值,以免由於精度誤差而四舍五入。 Double.MAX_VALUE ,由於尾數有53位,所以連續值之間差異很大。

System.out.println("Math.ulp(Double.MAX_VALUE) is " + Math.ulp(Double.MAX_VALUE));

1.9958403095347198E292

該值是2 971

您需要添加一個至少產生這么多的表達式才能溢出到Infinity 我之所以說“至少有這么多的收益”,是因為我可以通過添加2 970使其溢出,但是2 969沒有任何效果。

doubleTest += Math.pow(2.0, 969);

1.7976931348623157E308

doubleTest += Math.pow(2.0, 970);

Infinity

它看起來像2 970被四舍五入到2 971被添加到Double.MAX_VALUE ,但2 969被四舍五入到0 ,並且對之沒有影響。

對於float ,也發生了類似的過程,盡管這些值並不是很高。

浮點下溢

doubleTest = Double.MIN_VALUE;
doubleTest--;

這只是一個無窮小值減去1,實際上是一個負數。 這不會下溢。

指數而不是值變得太低而無法表示時,發生下溢,因此結果為0.0 2除以得到下溢。

doubleTest = Double.MIN_VALUE;
doubleTest /= 2;

0.0

整數/長溢出/下溢出

這些是期望值,因為您知道這些值“環繞”到值范圍的另一側。

這些“怪異”的結果並非真正針對Java。 只是相關IEEE標准所定義的浮動比大多數人所懷疑的要復雜得多。 但是在您的特定結果上: Float.MIN_VALUE是最小的浮點數,因此非常接近0。因此Float.MIN_VALUE - 1將非常接近-1。 但是,由於-1附近的浮點精度大於該差,因此得出-1。 對於Float.MAX_VALUE ,此值附近的浮點精度遠大於1,並且加1不會改變結果。

您的結果不一定非同尋常,只是浮點數通常是非常特定的,並且您的請求非常接近。 使用雙重數據類型時,我遇到了類似的問題。 只需仔細檢查,以確保您的代碼簽出了您所期望的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM