2010-02-13 21 views
10

考慮以下代碼:爲什麼Java中的短整數除法的結果類型不是一個短整數?

public class ShortDivision { 
    public static void main(String[] args) { 
     short i = 2; 
     short j = 1; 
     short k = i/j; 
    } 
} 

編譯此產生錯誤

ShortDivision.java:5: possible loss of precision 
found : int 
required: short 
     short k = i/j; 

因爲表達式i的類型/ J顯然INT,並且因此必須被強制轉換爲短。

爲什麼是i/j類型不淡?

+1

因爲將int轉換爲short可能會導致精度損失。 (-32768/-1) – 2010-02-13 09:06:04

回答

16

Java spec

5.6.2二元數值提升

當操作者施加的二進制數值提升到一對操作數,其中的每一個必須表示一個數值類型的值,則適用下列規則,以使用擴展轉換(§5.1.2),以操作數轉換爲必要的:

如果操作數的類型是雙,其他被轉換爲加倍。

否則,如果任一操作數的類型爲float,則另一個操作數轉換爲float。

否則,如果有操作數的類型的長,另一個被轉換爲長。

否則,兩個操作數都轉換爲int類型。

對於二進制操作,小的整數類型被提升到int和操作的結果爲int


編輯:爲什麼會這樣呢?最簡單的答案是Java從C中複製了這種行爲。更長的回答可能與所有現代機器至少執行32位本機計算有關,而實際上對於某些機器來說可能難以執行8位和16位操作。

參見:OR-ing bytes in C# gives int

+0

進一步:對某些運算符的操作數執行二進制數字提升: - 乘法運算符*,/和% – akf 2010-02-13 07:54:20

+0

好的,我知道語言規範說這個語言應該像這樣(否則編譯器不會首先產生錯誤)。但我不明白其背後的動機。爲什麼他們在進行分工之前推廣這些類型,而不是僅僅把短褲分開? – flodin 2010-02-13 08:01:01

+0

我的賭注是「這就是它在C中的方式」。 Java被設計爲對C++程序員有吸引力 - 要求事物是相同的 – 2010-02-13 08:58:17

2

關於動機:讓想象替代這種行爲,爲什麼他們不工作:

選擇1:結果應始終是相同的輸入。

應的結果是什麼添加一個int和短?

結果應該是兩個短褲相乘的結果?一般情況下的結果會符合整數,但因爲我們將截斷縮短,所以大多數乘法運算都會失敗。之後投射到int將無濟於事。

替代方法2:結果應該總是可以表示所有可能的輸出最小的類型。

如果返回類型很短,答案並不總是可以表示爲短。

短暫可以保存值-32,768至32,767。然後這個結果將導致溢出:

short result = -32768/-1; // 32768: not a short 

所以你的問題變成:爲什麼添加兩個整數不會返回一個長?兩個整數應該是什麼?長?一個BigNumber來覆蓋平方整數最小值的情況?

方案3:選擇大多數人可能最希望的時間

所以結果應該的事情:

  • INT兩個短褲相乘,或任何詮釋操作。
  • 如果加上或減去短褲,將短褲除以任何整數類型,再乘以兩個字節,...
  • 如果向右偏移一個字節,則爲byte,如果向左偏移,則爲int。如果他們沒有根本的邏輯
  • 等...

記住所有的特殊情況下會很困難。簡單地說:整數運算的結果總是一個整數。

+0

人們想要什麼,如果你再次設計它,並不總是那麼好。 QWERTY鍵盤排列就是一個很好的例子。最初的目的是*減慢打字員的工作,使打字機不會卡紙。不過,我無法想象使用其他任何東西,因爲我習慣了。 – 2010-02-13 08:50:31

+0

@Peter Lawrey:是的。如果亨利福特曾問過人們應該製造什麼樣的汽車,那麼許多人會要求購買配備** 6匹馬的購物車,而不是4輛。傾聽用戶的需求是件好事,但有時候您需要給他們與他們想要的不同,因爲他們甚至無法想象與他們習慣的不同的解決方案。 – 2010-02-13 09:18:21

+0

對於沒有操作符重載的語言,爲什麼不將結果設置爲(可能的最大結果)或(接收容器的大小)中較小的一個?在大多數情況下,這樣的規則將產生的代碼與使用方法#1產生算術正確結果的任何可能表達的代碼一樣小或小。例如,如果變量是32位,那麼'p =(x * y)/ z;'會做32x32-> 64乘法和64/32-32除法。如果'p'和'z'是16位,它將執行32x32-> 64乘法,64-32溢出檢查減少和32/16-> 16除法。 – supercat 2014-02-10 22:14:13

0

它只是一個設計選擇,與Java設計時支配語言的C/C++一致。

例如,可以實現i * j,以便從byte => short,short => int和int => long提升類型,這樣可以避免溢出,但不會。 (它在某些語言中是有效的)如果當前的行爲是需要的,可以使用Casting,但是丟失一些位會很清楚。

同樣可以從字節/短=> float或int/long => double提示i/j。

相關問題