首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

C++ 負浮點數截斷保留兩位小數(非四捨五入)實作方案

     編輯:程式設計綜合問答

問題分析

標準庫函數(如 std::round、printf("%.2f"))均採用四捨五入規則。對於負數,直接截斷(向零取整)與向下取整(floor)結果不同:

  • -1.2345 → 截斷:-1.23,四捨五入:-1.23
  • -1.2365 → 截斷:-1.23,四捨五入:-1.24
  • -1.6543 → 截斷:-1.65,四捨五入:-1.65

核心演算法:向零截斷

#include <iostream>
#include <cmath>

double truncateTwoDecimals(double n) {
    bool isNegative = n < 0;
    if (isNegative) n = -n;                    // 轉為正數處理
    n = std::trunc(n * 100.0) / 100.0;         // 乘100 → 截斷小數 → 除100
    return isNegative ? -n : n;                // 恢復符號
}

// C++11 起可用 std::trunc,舊標準可用 (int)(n * 100.0) / 100.0
// 注意:int 轉換屬於向零截斷行為,符合需求

完整可執行範例

#include <iostream>
#include <cmath>
#include <iomanip>

double truncateTwoDecimals(double n) {
    bool sign = n < 0;
    if (sign) n = -n;
    n = std::trunc(n * 100.0) / 100.0;
    return sign ? -n : n;
}

int main() {
    double testCases[] = {-1.2345, -1.2365, -1.6543, 1.2345, 1.2365, 1.6543, -0.001, -0.009};
    
    std::cout << std::fixed << std::setprecision(4);
    std::cout << "原始值\t\t截斷結果\t四捨五入\n";
    std::cout << "------------------------------------------\n";
    
    for (double val : testCases) {
        double truncated = truncateTwoDecimals(val);
        double rounded = std::round(val * 100.0) / 100.0;
        std::cout << val << "\t\t" << truncated << "\t\t" << rounded << "\n";
    }
    return 0;
}

輸出結果對照

原始值          截斷結果        四捨五入
------------------------------------------
-1.2345         -1.2300         -1.2300
-1.2365         -1.2300         -1.2400
-1.6543         -1.6500         -1.6500
1.2345          1.2300          1.2300
1.2365          1.2300          1.2400
1.6543          1.6500          1.6500
-0.0010         -0.0000         -0.0000
-0.0090         -0.0000         -0.0100

替代方案:字串操作法(避免浮點誤差)

#include <string>
#include <sstream>

std::string truncateTwoDecimalsStr(double n) {
    std::ostringstream oss;
    oss << std::fixed << std::setprecision(10) << n;  // 高精度轉字串
    std::string s = oss.str();
    
    size_t dotPos = s.find('.');
    if (dotPos != std::string::npos && dotPos + 3 < s.length()) {
        s = s.substr(0, dotPos + 3);  // 保留小數點後兩位
    }
    // 移除末尾多餘的零(可選)
    // s.erase(s.find_last_not_of('0') + 1, std::string::npos);
    // if (s.back() == '.') s.pop_back();
    return s;
}

注意事項

  1. 浮點精度:二進制浮點數無法精確表示某些十進制小數(如 0.1),大量運算後可能產生誤差
  2. 金融計算:涉及金額建議使用整數(分為單位)或專用十進制庫(如 Boost.Multiprecision/cpp_dec_float)
  3. C++20:可使用 std::format 簡化格式化輸出

總結

負數截斷保留兩位小數的核心是「取絕對值 → 乘100 → 向零取整 → 除100 → 恢復符號」。std::trunc 或 (int) 強制轉換均可實現向零截斷,配合符號處理即可正確應對正負數場景。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved