2014-02-16 25 views
1

沒有真正需要解決這個問題的方法,我只想知道爲什麼。 讓我們兩個數字:爲什麼我不能用一個負數來劃分大數目C++

#include <iostream> 
using namespace std; 

int main() 
{ 
    unsigned long long int a = 17446744073709551615; 
    signed long long int b = -30000000003; 
    signed int c; 
    c = a/b; 
    cout << "\n\n\n" << c << endl; 
} 

現在,最近我已經得到的答案是零。我的長整數的長度是8個字節,所以綽綽有餘地把它與未簽名的標籤。 C變量也應該足夠大來處理答案。 (根據谷歌的說法,它應該是-581 558 136)。所以......

編輯我想指出的是,在我的機器上...

使用numeric_limits一個仍遠遠withing最大的18446744073709551615和b的-9223372036854775808的最低限度內。

+0

爲什麼需要這麼大和毫無意義的數字? http://coliru.stacked-crooked.com/a/8f7b78a46536e533 – chris

+1

我的猜測是劃分是作爲無符號long long的一個劃分完成的,即b變成了一個非常大的無符號long long。因此結果爲0. – user515430

+0

嘗試首先將'a'轉換爲'signed long long int'。 – herohuyongtao

回答

6

得到答案,因爲使用它0

試試你原來的一些隱式轉換的發生,大多是不必要的。

unsigned long long int a = 17446744073709551615; 

一種無後綴十進制整數字面是int類型,long int,或long long int的;它從來沒有一個無符號類型。該特定值幾乎肯定超過了long long int(2 -1)的最大值。除非你的編譯器有一個寬度超過64位的有符號整數類型,否則這會使你的程序不合格。

添加ULL後綴以確保該文字是正確的類型:

unsigned long long int a = 17446744073709551615ULL; 

的值正好是2 -1和2 -1之間,所以它在適合一個64位無符號類型,但不是64位有符號類型。

(其實只是U就足夠了,但它不會傷害是明確的。)

signed long long int b = -30000000003; 

這不應該是一個問題。 30000000003是一些有符號的整數類型;如果您的編譯器支持至少64位寬的long long,則不會發生溢出。不過,只要你需要的a值後綴,它不會傷害是明確的:

signed long long int b = -30000000003LL; 

現在我們有:

signed int c; 
c = a/b; 

分割一unsigned long longsigned long long導致帶符號的操作數將被轉換爲unsigned long long。在這種情況下,被轉換的值是負值,所以它被轉換爲一個大的正值。將-30000000003轉換爲unsigned long long得到18446744043709551613。將17446744073709551615除以18446744043709551613得到零。

除非你的編譯器支持64位以上的整數寬(最不),你將不能夠直接通過17446744073709551615-30000000003得到一個數學上正確的答案,因爲沒有能夠代表兩個整數類型值。所有算術運算符(除換算運算符外)都需要相同類型的操作數,並根據需要應用隱式轉換。

在這種特殊情況下,您可以將17446744073709551615ULL除以30000000003ULL,然後考慮符號。 (檢查負整數除法的語言規則。)

如果您確實需要這樣做,您可以使用浮點(這意味着您可能會失去一些精度)或使用任意寬度的整數算術包如GMP

+0

這是一個相當不錯的答案。 不幸的後綴仍然會產生0.至於我的編譯器是否支持64位以上的數字。但是......然後......我並沒有計劃讓比我更長的無簽名的任何東西都可以玩。 – user3315127

0

b被視爲一個大於a的無符號數。因此,你作爲

c = abs(a)/abs (b) 
if ((a < 0 && b > 0) || (a> 0 && b < 0)) 
    return -c; 
return c; 
相關問題