2014-02-13 9 views
3

我有一個變量x類型float應該提高到一定的功率p。如果xdouble我本可以使用Math.pow(x, p)。是否有可能計算x^p以便結果也將是float在Java中提高浮動到一定的功率

+0

使用相同的方法。它將被隱式轉換爲「雙」。 – Maroun

+3

轉換爲double有什麼問題? –

+0

不符合標準的JDK。但是,你爲什麼不用「雙」呢? – fge

回答

5

double評估pow,並轉換爲float幾乎總是產生相同的結果作爲評價float實施pow。要看到這一點,請考慮精確的數學值xp。如果使用圓到最近的模式,它被正確舍入到double,然後正確舍入到float,結果與直接舍入到float相同,除非四捨五入到double跨過邊界移動該值其中四捨五入爲float的變化。

這些邊界僅在兩個可表示值之間的中點存在,在24 位一個有效數(計數最顯著位作爲0 位)的。但是在第53位發生的取整爲double。因此,四捨五入到double可能會導致一個值僅在比特24到53具有特定值時跨越float舍入邊界,如以下情況所示。

[有人應該檢查這些;很容易犯錯誤]

案例0:

   Bit 23 24 25-52 53 54… 
Original   1 0 11…11 1 anything 
Rounded to double 1 1 00…00 0 0… (53 above midpoint: rounds up, carries to higher bits) 
Then to float  0 0 00…00 0 0… (24 at midpoint, 23 is odd: rounds up, carries into bit 22, not shown) 
Directly to float 1 0 00…00 0 0… (24 below midpoint: rounds down) 

情況1:

   Bit 23 24 25-52 53 54… 
Original   0 1 00…00 0 anything except all zeroes 
Rounded to double 0 1 00…00 0 0… (53 below midpoint: rounds down) 
Then to float  0 0 00…00 0 0… (24 at midpoint, 23 is even: rounds down) 
Directly to float 1 0 00…00 0 0… (24 above midpoint: rounds up) 

情況2:

   Bit 23 24 25-52 53 54… 
Original   0 1 00…00 1 0… 
Rounded to double 0 1 00…00 0 0… (53 at midpoint, 52 is even: rounds down) 
Then to float  0 0 00…00 0 0… (24 at midpoint, 23 is even: rounds down) 
Directly to float 1 0 00…00 0 0… (24 above midpoint: rounds up) 

情況需要31位具有具體值,所以它發生在一次2 ,假設值均勻有效地分配。情況1是相同的,除了它還要求一位出現在無限多位的任何位置,其概率實際上是一位。情況2要求無限多個比特爲零,因此其概率爲零。至少在美學上,案例1和案例2吻合。

發生這些情況中的任何一種的總概率爲1英寸2 。

因此,將double結果四捨五入爲float的情況會產生與直接計算結果不同的結果。

最重要的是,大多數pow實現是不完善的。他們不知道在所有情況下都返回正確的舍入結果。 (這很難實現。)所以你可能會有不完美的結果。舍入到double,然後到float不會有明顯的差異。

2

你可以隨時編寫自己的小函數來完成它。

public float power(final float base, final int power) { 
    float result = 1; 
    for(int i = 0; i < power; i++) { 
     result *= base; 
    } 
    return result; 
} 

編輯:一些額外的測試

隨着人們在評論部分人士指出,如果得到的浮動證明太大而不能存儲在浮點值內,這將返回錯誤。

以下主要方法:

public static void main(final String[] args) { 
    System.out.println(power(Float.MAX_VALUE, 2)); 
} 

給我的結果:

Infinity 

很顯然,我的解決方案也有其侷限性。

編輯:進一步閱讀

爲了避免本的限制,我想知道你能否在計算過程中使用雙,然後就返回前將其轉換成爲一個浮點數。通過使用Math.pow()或更改上面的代碼。

請記住,這很可能導致其在this other SO post

+0

你覺得'float^someX'會怎麼樣?總是會返回一個* float *? –

+1

這個實現比'pow'多數整數值''double''參數的合理實現更糟糕。 –

+0

如果'result * base'返回的數字超過'float'所代表的最大值,則此方法將導致溢出並返回假結果。 – BackSlash

0

解釋了一些精度問題,您仍然可以使用

Math.pow(x, p); 

你浮法x將被轉換爲雙即使你不這樣做明確地做。麻煩的是,當你將返回的值作爲一個double值,然後你用它做了什麼。

編輯: 如果需要有一個方法返回一個浮點數,你仍然可以使用Math.pow,然後把你的轉換從double轉換回float,並且包含你自己的邏輯。

public float myPow(float x, float p) { 
    double dblResult = Math.pow(x, p); 
    float floatResult = (float)dblResult; // <-- Change to something safe. It may easily overflow. 
    return floatResult; 
} 
+0

謝謝,但我其實確實需要結果是一個浮動。我已經對這個問題進行了編輯,以澄清這一點。 – snakile

+0

您仍然可以使用Math.pow並處理結果(例如將其重新轉換爲浮動,但請注意溢出)。無論您選擇哪種解決方案,都需要您進行某種處理或編碼,而更關心您將如何處理這一問題。 – DanielBarbarian

+0

我認爲你犯了一個錯字,因爲現在這個問題說你想要把結果作爲一個雙精度。 – DanielBarbarian