C 捨進位函式:rint() 與 round()

14568 단어 c

태그: C

C 捨進位函式:rint() 與 round()



Math.h h 有 round() 和 和 rint() 兩 個 個 看起來 看起來 很 很 的 函式 函式, 但是 卻 有 有 細微差異 細微差異, 簡單 來 說, round() 就 是 我們 熟悉 熟悉 的 的 的 四捨五 入 入, 而 rint() 是 可 變更 變更 變更 變更 變更 是 是 是 是 是捨進位方式的版本.

round() 函式


round() 採用四捨五入, 例如:

#include<stdio.h>
#include<math.h>

int main() {
  printf("%.20f\n", round(4.3));
  printf("%.20f\n", round(-4.3));
  printf("%.20f\n", round(3.5));
  printf("%.20f\n", round(-3.5));
}


執行結果如下:

4.00000000000000000000
-4.00000000000000000000
4.00000000000000000000
-4.00000000000000000000


rint() 실행


rint() 函式猛看和 round() 好像一樣, 例如把剛剛的範例從 round() 改成使用 rint() :

#include<stdio.h>
#include<math.h>

int main() {
  printf("%.20f\n", rint(4.3));
  printf("%.20f\n", rint(-4.3));
  printf("%.20f\n", rint(3.5));
  printf("%.20f\n", rint(-3.5));
}


執行結果如下:

4.00000000000000000000
-4.00000000000000000000
4.00000000000000000000
-4.00000000000000000000


沒有什麼特別的, 但是如果執行以下的程式:

#include<stdio.h>
#include<math.h>

int main() {
  printf("%.20f\n", rint(4.5));
  printf("%.20f\n", rint(-4.5));
}


執行結果如下:

4.00000000000000000000
-4.00000000000000000000


咦 咦 為什麼?? 捨去 小數 而 不 是 是 進位 進位 呢 呢? 這 是 是 因為 因為 在 預設 預設 的 捨進位 模式 下, rint() 是 捨進 捨進 位 位 到 較 近 的 整數 整數 但 但 小數 部分 剛好 剛好 剛好 就 就 是 是 0.5, 則 會 捨進位 捨進位 捨進位 捨進位 捨進位 成 成 但 如果 如果 如果 如果 如果 如果 如果 如果 如果 如果 如果 如果 如果 如果 小數 小數 小數 小數 小數 小數 部分 部分 部分 部分 部分 部分 剛好 剛好 剛好 剛好 就 就 就 就 是 位 位 到 較 較 近 的 的 的偶數 偶數 以 以. 的 例子 來 說 說, 如果 是 3.5, 3.5, 因為 3 是 奇數, 所以 會 進位 變成 4 ; 但若 但若 4.5, 因為 4 本身 就 是 偶數, 所以 就 變成 捨 去 小數 不 進位 進位 了 了 了 捨 捨 捨 捨

要注意的是, 因為是捨進位到比較近的整數, 所以並不是只看小數第一位, 例如:

#include<stdio.h>
#include<math.h>

int main() {
  printf("%.20f\n", rint(4.5001));
  printf("%.20f\n", rint(-4.5001));
}


執行結果就跟前一個例子不一樣了:

5.00000000000000000000
-5.00000000000000000000


這是因為 4.5001 比較靠近 5, 所以會進位成整數 5.只有在小數剛好就是介於兩個整數之間的0.5 時, 才會依剸成進佛的0.5 時, 才會依剸成進佾

變更捨進位模式


rint() 0.5 要捨位還是進位是可以變更的, 你可以透過義在 fenv.h 內的 fesetround() 設定, 共有以下幾種模式:


模式常數
설명


FE_DOWNWARD
捨進位到比較小的整數, 結果就會跟 floor() 一樣

FE_TONEAREST
捨進位到較近的整數, 遇到 0.5 時捨進位成偶數

FE_TOWARDZERO
捨進位到靠近 0 的整數, 也就是無條件捨去小數, 就跟 trunc() 一樣

FE_UPWARD
捨進位成比較大的整數, 也就是 ceil()



預設 預設 預設 的 是 是 FE_TONEAREST, 這個 模式 模式 主要 主要 是 是 想要 解決 統計 統計 數值 時 時 四捨五 入 會 讓 讓 原本 分布 分布 平均 的 的 資料 在 在 捨進位 後 分布 不 平均 平均 因為 0.5 進位 進位, 可能 會 讓 數值 偏 高 高, 因此 改 成 成 成 不 不 平均 平均捨進位成偶數, 就相當於讓 0.5 有一半的機會進位, 一半的機會捨去.

如果更改捨進位模式, 例如:

#include<stdio.h>
#include<math.h>
#include<fenv.h>

int main() {
  fesetround(FE_DOWNWARD);
  printf("%.20f\n", rint(4.3));
  printf("%.20f\n", rint(-4.3));
  printf("%.20f\n", rint(3.5));
  printf("%.20f\n", rint(-3.5));
  printf("%.20f\n", rint(4.5));
  printf("%.20f\n", rint(-4.5));
}


執行結果就會變成:

4.00000000000000000000
-5.00000000000000000000
3.00000000000000000000
-4.00000000000000000000
4.00000000000000000000
-5.00000000000000000000


就會捨進位成較小的整數, 這個結果就跟你用 floor() 一樣:

#include<stdio.h>
#include<math.h>
#include<fenv.h>

int main() {
  printf("%.20f\n", floor(4.3));
  printf("%.20f\n", floor(-4.3));
  printf("%.20f\n", floor(3.5));
  printf("%.20f\n", floor(-3.5));
  printf("%.20f\n", floor(4.5));
  printf("%.20f\n", floor(-4.5));
}


執行結果如下:

4.00000000000000000000
-5.00000000000000000000
3.00000000000000000000
-4.00000000000000000000
4.00000000000000000000
-5.00000000000000000000


小結



使用 rint() 因為會受到捨進位模式設定的影響, 我個人建議就直接使用函式名稱直白明確的 round()ceil()floor() 6. 襔 襔 trunc()

좋은 웹페이지 즐겨찾기