iT邦幫忙

2

【魔鬼般的c++語法細節】(1) 5/2是2.5還是2?

c++

哈囉~ 大家好,我是心原一馬,
內心原來一心喜歡打程式碼。

俗話說:「魔鬼藏在細節裡。」
尤其是像c++語言這樣嚴謹又複雜的語法,
更是藏著數不盡的細節,
若是不從小處開始留意,
常常會埋下數不盡難找的臭蟲(bug,指程式上的錯誤)

因此,本系列文嘗試儘可能挖掘出c++語法上的細節,
容易出錯的地方整理成系列文,
讀者若有什麼想知道的語法細節,
也可在留言區提出,做為小馬撰文的參考哦~

那麼我們開始吧

除法是「整數」的還是「小數」的?

基礎的加減乘除運算,
應該是初學c++都會碰到的主題吧,
譬如說「有5個pizza,分給2人,每人分得幾個?」,
我們心目中的答案是2.5個,
寫個c++程式來算一下:

double d = 5/2;
std::cout << d << std::endl;

這時試著執行一下程式,
卻發現結果是2而非想像中的2.5
明明d的型態已經宣告成double(浮點數)了啊?

因為當c++在做除法時,
如果被除數和除數都是整數的話,
那麼除法就會只取得商數
餘數的部分直接捨去(不會四捨五入)

不信的話可以做個測試:

double d = 19/10;
std::cout << d << std::endl;

嘗試做19/10,答案雖然是1.9,比較靠近2
但印出來的答案卻是1

那要怎麼樣可以讓程式真的做小數點的除法運算呢?
希望的結果是5/2會變成2.5

答案很簡單,你寫double d = 5/2.0;double d = 5.0/2
只要除數與被除數兩者有一個是浮點數,
那麼除法便會進行小數點的運算,
或者,你可以在25的前面加上(double)使數字轉型為浮點數

舉例來說,底下這四種寫法都可以順利印出2.5:

std::cout << 5.0/2 << std::endl;
std::cout << 5/2.0 << std::endl;
std::cout << (double)5/2 << std::endl;
std::cout << 5/(double)2 << std::endl;

結論:

  • 若除法中除數與被除數有一個是浮點數,則為小數點的除法
  • 若除法中除數與被除數都是整數,則為整數的除法

運算符號的兩端是什麼類型,就會做什麼類型的運算,
如果類型不同,範圍較小的型別原則上會轉型為較大的型別,
譬如說用浮點數除以整數會轉型成浮點數運算

這點相當重要,
可以幫助我們理解為什麼明明宣告了一個long long長整數型別,
處理long long L = 10000000*10000000;的計算竟然仍會產生「溢位」的問題
(關於溢位的概念留到之後幾篇再講,
心裡有個概念知道要進行算術運算的型別需一致,
否則可能會產生意料之外的後果)

課後練習

這邊有一支程式,
讀入使用者輸入的兩個整數,
想要計算到小數點後兩位的結果

#include <stdio.h>
#include <iostream>

int main()
{
    int a, b;
    std::cin >> a >> b;
    double d = a/b;
    printf("%.2f", d);
    return 0;
}

譬如說輸入10 3
希望結果印出3.33
但這支程式有些地方寫錯了,
請修改double d = a/b;這一行,
讓程式能印出正確的結果


尚未有邦友留言

立即登入留言