2013-11-26 62 views
2

我正在編寫物理模擬,最近我遇到了異常結果。我成功地調試我的程序,錯誤是在一個大雙的劃分由一個大INT,形式的東西:劃分大型雙倍大int

cout << my_large_double/my_large_int << endl 

與秩序-10^{9}和產品的my_large_double我兩個int是訂單的10^{9}正在恢復一些積極1. 我通過徵收轉換分母增加一倍固定它的順序:

cout << my_large_double/((double)my_large_int1*my_large_int2) << endl 

但我想明白的地方是錯誤來自哪裏,並且有沒有辦法阻止它們通常發生?

更新:我跳過了一個重要的細節,在我的第一個問題:int實際上是兩個整數的乘積。

+0

可能是由於環回,因爲在int的最大值可能會達到,所以它迴環 – AsG

+0

@john經驗告訴我,它解決了問題,如果你想嘗試在你身邊。 – Liam

+0

我相信您的問題已經在這裏找到答案: http://stackoverflow.com/questions/3051135/dividing-a-double-with-integer –

回答

4

這取決於表達式的寫法。

如果你這樣寫:

my_large_double/my_large_int1/my_large_int2 

那麼它等同於:

(my_large_double/my_large_int1)/my_large_int2 

這應該給你相當準確的結果; my_large_int1在第一部分之前被提升爲double,並且my_large_int2在第二部分之前被提升爲double

如果你這樣寫:

my_large_double/(my_large_int1 * my_large_int2) 

然後乘兩個整數變量的類型進行,並根據它們的值,你可以有溢出(它可以給你比一個更小的值數學產品 - 儘管嚴格來說,有符號整數溢出的行爲是未定義的)。

要記住的重要的事情是,在大多數情況下,每個C表達是有效地隔離評價;它的類型不受其出現的上下文的影響。表達式my_large_int1 * my_large_int2是整數乘法,即使結果是浮點除法的操作數或分配給浮點變量。

操作數都是整數的任何操作都是整數操作。如果一個操作數是double,另一個是int,該int操作數提升爲double

即使這樣:

double temp = my_large_int1 * my_large_int2; 
... my_large_double/temp ... 

將使用該結果來初始化temp之前執行的整數乘法,以及這樣的:

my_large_double/(double)(my_large_int1 * my_large_int2) 

有同樣的問題。

正如您看到的,該解決方案是投整數操作數的一個或兩個double

my_large_double/((double)my_large_int1 * (double)my_large_int2) 

(你還不如投他們兩個,只是爲了對稱和透明度。)

1

一個IEEE format double可以容納一個int沒有精確度損失高達53位,而int典型的31位。你的解決方案是一個很好的解決方案,預先轉換爲double,這樣你就不會在乘法中產生整數溢出。

+0

是的,有沒有一種通用的方法來防止int在運行時溢出? – Liam

+0

使用雙長還是長? – gregory561

+0

@ gregory561:沒有實際的保證,long long比int更寬(儘管通常是這樣)。 –