2010-09-13 37 views
1

這可能很簡單,但我沒有得到我期待的結果。我道歉,如果這是一個愚蠢的問題,我只是不知道谷歌。解釋有關將float分配給int的簡單問題

最簡單的方法是用一些代碼:

int var = 2.0*4.0; 

NSLog(@"%d", 2.0*4.0);//1 
NSLog(@"%d", var);//2 

if ((2.0*4.0)!=0) {//3 
    NSLog(@"true"); 
} 

if (var!=0) {//4 
    NSLog(@"true"); 
} 

這將產生以下的輸出:

0 //1 
8 //2 
true //3 
true //4 

,我不明白的是線//1的一個。爲什麼所有其他的轉換(我假設正確的詞是「鑄造」,請糾正我,如果我錯了)浮動到一個int,但在NSLog裏面它沒有發生。這是否與字符串格式%d參數有關,它很模糊(缺少更好的單詞)?

回答

4

你告訴您傳遞它與@"%d"格式說明一個整數的NSLog,但你沒有真正給它一個整數;你給它一個雙精度的浮點值(8.0,正好如此)。當你對NSLog說謊時,它的行爲是不確定的,你會得到像這樣的意外結果。

不要撒謊NSLog。如果你想的2.0*4.0結果轉換成印刷前的整數,你需要做的是明確的:

NSLog(@"%d", (int)(2.0*4.0)); 

相反,如果你要打印的2.0*4.0結果爲雙精度浮點數,你需要使用不同的格式說明:

NSLog(@"%g", 2.0*4.0); 

更廣泛地說,這是採用可變數量的參數和一些格式字符串來告訴它如何解釋他們的任何功能都是如此。您應該確保您傳遞的數據與相應的格式說明符匹配;隱式轉換不會發生在你身上。

0

格式字符串%d需要一個十進制數,表示基數爲10的整數,而不是浮點數。你想有什麼是%f如果你想獲得它打印出來8.0

+0

是。 '%d'表示「小數」,而不是「雙」。 – 2010-09-13 22:59:30

+0

或'%g',智能地選擇固定小數和科學格式。 – Potatoswatter 2010-09-13 23:00:03

0

NSLog的第一個參數是格式字符串,那麼第二個(及後續)參數可以是任何類型。編譯器在編譯時不知道類型應該是什麼,所以不會試圖將它們轉換爲任何東西。在運行時,NSLog假定第二個(及後續)參數與格式字符串中指定的相同。如果出現意想不到的錯誤並且通常會發生不愉快的事情。

總結;確保在第二個(及後續)參數中傳遞正確類型的變量。

2

在示例2,3和4中,float被分配​​給int(將其轉換)或與int(也轉換它)進行比較。然而,在1中,你將float作爲參數傳遞給一個函數。 printf函數允許初始格式字符串之後的所有參數具有任何類型,因此這是有效的。但是由於編譯器並不知道你的意思是它是一個int(記住,你沒有做任何事情讓編譯器知道),所以float被作爲一個浮點值傳遞。當printf看到%d格式化說明符時,它會從參數列表中彈出足夠的字節作爲int,並將這些字節解釋爲int。這些字節看起來像一個整數0。

3

首先,您從未在您的程序中使用過float。他們是double s。

其次,NSLog,printf等的參數不會自動轉換爲您使用%d%f指定的參數。它遵循無類型參數的標準提升規則。請參閱the ISO specification, sec 6.5.2.2.6 and 6.5.2.2.7。注超級怪異的規則,這些功能裏面,

  • 一個float將自動提升爲double
  • 和比int小晉升爲int任意整數。 (見6.3.1.1.2)

所以,嚴格地說,規範%f沒有呈現出float,但double。見同一文件,Sec。 7.19.6.1.8。

請注意,在你的情況1和3,促銷是double

+0

+ 1 for'no float - only double' – 2010-09-13 23:15:47

+0

如果要節省空間,通常用於大型數組(不是一些堆棧變量),則使用浮點數而不是雙精度浮點數。 – 2010-09-14 14:31:37