2017-09-16 227 views
0
#include <math.h> 
#include <stdio.h> 

void main() { 
    int decimal, count, binary, digit; 
    printf("Enter the number : "); 
    scanf("%d", &decimal); 
    count = 0; binary = 0; 
    while (decimal > 0) { 
     digit = decimal % 2; 
     binary = binary + digit * pow(10, count); 
     decimal = decimal/2; 
     ++count; 
    } 
    printf("Binary form : %d", binary); 
} 

我使用上面的代碼將十進制轉換爲二進制。但是,問題在於輸出。功能錯誤

Input   : 12 
Expected Output : 1100 
Actual Output : 1099 

[IMG] https://i.imgur.com/1mZlMQN.png[/img]

此問題持續其他輸入太。只有8個給出正確的輸出。

那麼有人可以解釋爲什麼會發生這種情況?當我將它移植到C++中時,這個錯誤也會顯示出來。

PS:在使用pow檢查數字是否是Armstrong及其迴文時,此錯誤也會彈出。

+3

你確定嗎?這甚至不可能... –

+1

https://repl.it/LLhY/0我得到'1100' – kaza

+0

你不想使用'pow'這種東西。保持運行乘數,每次乘以2或10。 'pow'有不準確之處。 –

回答

3

pow(x, y)最有可能實現爲exp(y * log(x))它可以出乎意料地小的積分論點。如果結果被截斷爲整數,這將以特別的病態方式表現出來。

故事的寓意是在整數運算中避免使用pow函數。

在你的情況下,保持一個運行係數連續乘以10將是適當的。只要小心你不要溢出你的int類型;上限可以小至32767

+0

我建議避免混合浮點數和整數。 PS在這樣一個簡單的代碼中使用'pow'函數是極端懶惰的表現。 –

5

問題來自double算術的有限精度。 pow(10, count)可以計算爲exp(log(10) * count),其可以產生非常接近但與實際整數結果不同的值。如果此值小於數學值,則轉換爲int不會圓整到最接近,它將佔用整數部分將成爲前一個整數,因此99而不是100

您應該改用整數算術:

#include <stdio.h> 

int main(void) { 
    int decimal, binary, digit, pow10; 
    printf("Enter the number : "); 
    if (scanf("%d", &decimal) == 1) { 
     binary = 0; 
     pow10 = 1; 
     while (decimal > 0) { 
      digit = decimal % 2; 
      decimal /= 2; 
      binary = binary + digit * pow10; 
      pow10 *= 10; 
     } 
     printf("Binary form: %d\n", binary); 
    } 
    return 0; 
} 

注意,有在你的代碼中的一些其他問題:

  • 不帶參數的原型爲mainint main(void)
  • 您應該在輸出結束時打印換行符。
  • 您應該測試scanf()的返回值。
  • 您的方法本質上限於低於2047的整數值(具有32位int)。

這裏是一個改進版本:

#include <limits.h> 
#include <stdio.h> 

int main(void) { 
    unsigned long long decimal; 
    printf("Enter the number: "); 
    if (scanf("%llu", &decimal) == 1) { 
     char binary[sizeof(decimal) * CHAR_BIT + 1]; 
     char *p = binary + sizeof(binary); 
     *--p = '\0'; 
     while (decimal > 1) { 
      *--p = '0' + (decimal & 1); // '0' or '1' for all encodings 
      decimal >>= 1; 
     } 
     *--p = '0' + decimal; 
     printf("Binary form: %s\n", binary); 
    } 
    return 0; 
} 
+0

請注意,pow不一定要以這種方式實現,儘管它很可能是 - 特別是IEEE754。 – Bathsheba

+0

我會說「限於1023及以下的整數值」。更大的值,'pow10 * = 10;'溢出。 – chux

+0

@chux:好點:我的實現有這個問題,但是如果'pow(10,count)'表現正確,OP的方法可能會上升到2047。 – chqrlie

1

我想你的第一個問題是你的類型 - 你似乎想建立一個二進制數整數表示,和你還使用戰俘,其中有一個簽名:

double pow(double x, double y) 

所以你加入雙浮整數。你確定要這麼做嗎?

你可能會更好地通過基本循環做分隔/ mod並構建一個字符串並打印它。這是在這裏回答https://math.stackexchange.com/questions/111150/changing-a-number-between-arbitrary-bases

此外,大或小的排名可能會咬你,但這是在你的作業問題的範圍?

+0

這些考慮很有趣,但不是OP問題的確切答案 – chqrlie