2013-12-17 57 views
0

一些C我工作的代碼有一個int設置爲-145。取決於格式,該值將返回爲0.00-145。採取以下措施printf格式f與Python中的d

int a = -145; 

printf("%.2lf", a); // returns 0.00 
printf("%.2ld", a); // returns -145 

第一個問題是第一行是如何返回0.00?第二個問題是如何在Python中返回0.00

在衆多的迭代我試過,這裏有幾個:

a = -145 

"%0.2lf" % a # -145.00 
"%0.2ld" % a # -145 
"%0.2li" % a # -145 
"%0.2f" % a # -145.00 
+1

當然@ouah是正確的:C沒有定義你所展示的代碼中發生了什麼;它會在不同的平臺上有所不同,並且可能會導致顯示亂碼或崩潰。 C的'printf'系列以這種方式出了名的錯誤。要回答你的第二個問題,你不能以這種方式「欺騙」Python--沒有辦法讓Python將-145當作除了它之外的東西:一個整數。 –

+0

奇怪但好的謝謝。 –

回答

4
int a = -145; 

printf("%.2lf", a); // returns 0.00 
printf("%.2ld", a); // returns -145 

兩個函數調用調用未定義的行爲。打印int的正確轉換說明符是d而不是lf(對於double),而不是ld(對於long)。

0

第二個問題是如何在Python中返回0.00

如果你堅持:

import struct 

def misinterpret_int_as_double(n): 
    int_bytes = struct.pack('i', n) 
    padding = b'\x00' * (struct.calcsize('d') - struct.calcsize('i')) 
    return struct.unpack('d', int_bytes + padding)[0] 

>>> misinterpret_int_as_double(-145) 
2.1219957193e-314 

實際上,這就是你的C代碼做幕後。 C不會對調用可變參數函數的...部分中傳遞的參數進行任何類型檢查(編譯時爲運行時)。什麼情況是,存儲printf的論點存儲器包含:

  1. 的指針字符串字面"%.2lf
  2. 表示數字-145的字節。 (在x86-32或x86-64上,這是4個字節91 FF FF FF。)
  3. 一些垃圾數據。 (在上面的Python代碼,這被認爲是全零,但在你的C程序就不需要。)

printf功能看到lf符並預期double。因此,它將下列字節解釋爲91 FF FF FF xx xx xx xx(其中xx =垃圾)。對於垃圾可能值的大約1/4(包括00 00 00 00),該數量足夠小以圓化爲零。

請注意,我已經假定了一堆東西:你有一個小端系統,4字節的int和8字節的double。該函數參數在內存中以升序傳遞。而且你的代碼不會出現段錯誤。 YMMV在其他硬件/ OS /編譯器組合上。這就是未定義的行爲。

Python的工作方式不同,因爲它的安全類型。如果您將「錯誤的」類型傳遞給str%運算符,它將通過調用魔術__float__方法(或__str____int__或取決於其格式的任何內容)自動將操作數轉換爲正確的類型。