Skip to content

C++ 数字与数值

概述

数字和数值运算是编程的基础。C++提供了丰富的数值类型和数学函数库,支持从基本的算术运算到复杂的数学计算。本章将介绍数值类型、数学运算、精度处理以及相关的最佳实践。

🔢 数值类型概览

整数类型范围

cpp
#include <iostream>
#include <climits>

int main() {
    std::cout << "=== 整数类型范围 ===" << std::endl;
    
    // 有符号整数类型
    std::cout << "char: " << (int)CHAR_MIN << " 到 " << (int)CHAR_MAX << std::endl;
    std::cout << "short: " << SHRT_MIN << " 到 " << SHRT_MAX << std::endl;
    std::cout << "int: " << INT_MIN << " 到 " << INT_MAX << std::endl;
    std::cout << "long long: " << LLONG_MIN << " 到 " << LLONG_MAX << std::endl;
    
    // 无符号整数类型
    std::cout << "\n无符号类型最大值:" << std::endl;
    std::cout << "unsigned int: " << UINT_MAX << std::endl;
    std::cout << "unsigned long long: " << ULLONG_MAX << std::endl;
    
    // 类型大小
    std::cout << "\n类型大小(字节):" << std::endl;
    std::cout << "int: " << sizeof(int) << std::endl;
    std::cout << "long: " << sizeof(long) << std::endl;
    std::cout << "long long: " << sizeof(long long) << std::endl;
    
    return 0;
}

浮点类型特性

cpp
#include <iostream>
#include <cfloat>
#include <iomanip>

int main() {
    std::cout << "=== 浮点类型特性 ===" << std::endl;
    
    // 精度位数
    std::cout << "float 精度: " << FLT_DIG << " 位" << std::endl;
    std::cout << "double 精度: " << DBL_DIG << " 位" << std::endl;
    
    // 类型大小
    std::cout << "float: " << sizeof(float) << " 字节" << std::endl;
    std::cout << "double: " << sizeof(double) << " 字节" << std::endl;
    
    // 精度演示
    std::cout << "\n=== 精度演示 ===" << std::endl;
    float f = 1.23456789f;
    double d = 1.23456789;
    
    std::cout << std::setprecision(10);
    std::cout << "float: " << f << std::endl;
    std::cout << "double: " << d << std::endl;
    
    return 0;
}

➕ 基本数学运算

算术运算符

cpp
#include <iostream>

int main() {
    std::cout << "=== 基本算术运算 ===" << std::endl;
    
    int a = 15, b = 4;
    double x = 15.0, y = 4.0;
    
    // 整数运算
    std::cout << "整数运算 (a=" << a << ", b=" << b << "):" << std::endl;
    std::cout << "a + b = " << (a + b) << std::endl;
    std::cout << "a - b = " << (a - b) << std::endl;
    std::cout << "a * b = " << (a * b) << std::endl;
    std::cout << "a / b = " << (a / b) << " (整数除法)" << std::endl;
    std::cout << "a % b = " << (a % b) << " (取余)" << std::endl;
    
    // 浮点运算
    std::cout << "\n浮点运算 (x=" << x << ", y=" << y << "):" << std::endl;
    std::cout << "x / y = " << (x / y) << " (浮点除法)" << std::endl;
    
    // 复合赋值运算符
    std::cout << "\n=== 复合赋值运算符 ===" << std::endl;
    int num = 10;
    std::cout << "初始值: " << num << std::endl;
    
    num += 5;   std::cout << "num += 5: " << num << std::endl;
    num -= 3;   std::cout << "num -= 3: " << num << std::endl;
    num *= 2;   std::cout << "num *= 2: " << num << std::endl;
    num /= 4;   std::cout << "num /= 4: " << num << std::endl;
    
    // 自增自减
    std::cout << "\n=== 自增自减运算符 ===" << std::endl;
    int i = 5;
    std::cout << "i++ = " << i++ << " (后自增)" << std::endl;
    std::cout << "++i = " << ++i << " (前自增)" << std::endl;
    
    return 0;
}

数学函数库

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

int main() {
    std::cout << std::fixed << std::setprecision(4);
    
    std::cout << "=== 基本数学函数 ===" << std::endl;
    double num = 16.0;
    std::cout << "sqrt(16): " << sqrt(num) << std::endl;
    std::cout << "pow(2, 4): " << pow(2, 4) << std::endl;
    std::cout << "exp(1): " << exp(1) << std::endl;
    std::cout << "log(10): " << log(10) << std::endl;
    
    std::cout << "\n=== 三角函数 ===" << std::endl;
    double angle = M_PI / 4;  // 45度
    std::cout << "sin(π/4): " << sin(angle) << std::endl;
    std::cout << "cos(π/4): " << cos(angle) << std::endl;
    std::cout << "tan(π/4): " << tan(angle) << std::endl;
    
    std::cout << "\n=== 取整函数 ===" << std::endl;
    double decimal = 3.7;
    std::cout << "原值: " << decimal << std::endl;
    std::cout << "ceil: " << ceil(decimal) << std::endl;
    std::cout << "floor: " << floor(decimal) << std::endl;
    std::cout << "round: " << round(decimal) << std::endl;
    
    std::cout << "\n=== 其他函数 ===" << std::endl;
    std::cout << "abs(-5): " << abs(-5) << std::endl;
    std::cout << "fabs(-5.5): " << fabs(-5.5) << std::endl;
    std::cout << "fmod(7.5, 2.5): " << fmod(7.5, 2.5) << std::endl;
    
    return 0;
}

🎯 数值精度和比较

浮点精度问题

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

int main() {
    std::cout << std::fixed << std::setprecision(20);
    
    std::cout << "=== 浮点精度问题 ===" << std::endl;
    
    // 典型的浮点精度问题
    double a = 0.1;
    double b = 0.2;
    double sum = a + b;
    
    std::cout << "0.1 + 0.2 = " << sum << std::endl;
    std::cout << "是否等于0.3? " << (sum == 0.3 ? "是" : "否") << std::endl;
    
    // 安全的浮点比较
    std::cout << "\n=== 安全的浮点比较 ===" << std::endl;
    
    auto isEqual = [](double x, double y, double epsilon = 1e-9) {
        return std::abs(x - y) < epsilon;
    };
    
    std::cout << "使用epsilon比较:" << std::endl;
    std::cout << "0.1 + 0.2 ≈ 0.3? " << (isEqual(sum, 0.3) ? "是" : "否") << std::endl;
    
    return 0;
}

舍入和格式化

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

// 自定义舍入函数
double roundToDecimalPlaces(double value, int decimalPlaces) {
    double factor = std::pow(10.0, decimalPlaces);
    return std::round(value * factor) / factor;
}

int main() {
    std::cout << std::fixed;
    
    std::cout << "=== 舍入方法 ===" << std::endl;
    double value = 2.675;
    
    std::cout << std::setprecision(3) << "原值: " << value << std::endl;
    std::cout << std::setprecision(2);
    std::cout << "四舍五入到2位: " << roundToDecimalPlaces(value, 2) << std::endl;
    std::cout << "向上取整: " << std::ceil(value * 100) / 100 << std::endl;
    std::cout << "向下取整: " << std::floor(value * 100) / 100 << std::endl;
    
    std::cout << "\n=== 格式化输出 ===" << std::endl;
    double pi = 3.141592653589793;
    
    std::cout << "2位小数: " << std::setprecision(2) << pi << std::endl;
    std::cout << "4位小数: " << std::setprecision(4) << pi << std::endl;
    std::cout << "科学记数法: " << std::scientific << pi << std::endl;
    
    return 0;
}

🔀 数值转换

类型转换和字符串转换

cpp
#include <iostream>
#include <string>

int main() {
    std::cout << "=== 数值类型转换 ===" << std::endl;
    
    // 隐式转换
    int i = 42;
    double d = i;  // int to double (安全)
    std::cout << "int到double: " << i << " -> " << d << std::endl;
    
    double d2 = 3.14159;
    int i2 = static_cast<int>(d2);   // 显式转换
    std::cout << "double到int: " << d2 << " -> " << i2 << std::endl;
    
    // 字符串转换
    std::cout << "\n=== 字符串转换 ===" << std::endl;
    
    // 数值到字符串
    int num = 123;
    double decimal = 45.67;
    
    std::string str1 = std::to_string(num);
    std::string str2 = std::to_string(decimal);
    
    std::cout << "to_string: " << num << " -> \"" << str1 << "\"" << std::endl;
    std::cout << "to_string: " << decimal << " -> \"" << str2 << "\"" << std::endl;
    
    // 字符串到数值
    std::string strNum = "987";
    std::string strDecimal = "12.34";
    
    try {
        int converted1 = std::stoi(strNum);
        double converted2 = std::stod(strDecimal);
        
        std::cout << "stoi: \"" << strNum << "\" -> " << converted1 << std::endl;
        std::cout << "stod: \"" << strDecimal << "\" -> " << converted2 << std::endl;
    }
    catch (const std::exception& e) {
        std::cout << "转换错误: " << e.what() << std::endl;
    }
    
    return 0;
}

🎲 随机数生成

现代C++随机数

cpp
#include <iostream>
#include <random>
#include <vector>
#include <algorithm>

int main() {
    std::cout << "=== 现代C++随机数生成 ===" << std::endl;
    
    // 随机数引擎
    std::random_device rd;  // 硬件随机数
    std::mt19937 gen(rd()); // Mersenne Twister生成器
    
    // 均匀整数分布
    std::cout << "=== 均匀整数分布 (1-10) ===" << std::endl;
    std::uniform_int_distribution<> intDist(1, 10);
    
    for (int i = 0; i < 10; i++) {
        std::cout << intDist(gen) << " ";
    }
    std::cout << std::endl;
    
    // 均匀实数分布
    std::cout << "\n=== 均匀实数分布 (0.0-1.0) ===" << std::endl;
    std::uniform_real_distribution<> realDist(0.0, 1.0);
    
    for (int i = 0; i < 5; i++) {
        std::cout << std::fixed << std::setprecision(4) << realDist(gen) << " ";
    }
    std::cout << std::endl;
    
    // 随机洗牌
    std::cout << "\n=== 随机洗牌 ===" << std::endl;
    std::vector<int> deck = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    
    std::cout << "原始: ";
    for (int card : deck) std::cout << card << " ";
    std::cout << std::endl;
    
    std::shuffle(deck.begin(), deck.end(), gen);
    
    std::cout << "洗牌后: ";
    for (int card : deck) std::cout << card << " ";
    std::cout << std::endl;
    
    return 0;
}

随机数应用示例

cpp
#include <iostream>
#include <random>
#include <map>

// 随机数工具类
class RandomUtils {
private:
    std::mt19937 gen_;
    
public:
    RandomUtils() : gen_(std::random_device{}()) {}
    
    int randomInt(int min, int max) {
        std::uniform_int_distribution<> dist(min, max);
        return dist(gen_);
    }
    
    double randomReal(double min, double max) {
        std::uniform_real_distribution<> dist(min, max);
        return dist(gen_);
    }
    
    bool randomBool(double probability = 0.5) {
        std::bernoulli_distribution dist(probability);
        return dist(gen_);
    }
};

int main() {
    RandomUtils random;
    
    std::cout << "=== 随机数应用示例 ===" << std::endl;
    
    // 模拟骰子
    std::cout << "=== 模拟投掷骰子 ===" << std::endl;
    std::map<int, int> diceResults;
    
    for (int i = 0; i < 600; i++) {
        int roll = random.randomInt(1, 6);
        diceResults[roll]++;
    }
    
    for (const auto& [face, count] : diceResults) {
        std::cout << "点数 " << face << ": " << count << " 次" << std::endl;
    }
    
    // 概率事件
    std::cout << "\n=== 概率事件模拟 ===" << std::endl;
    int successCount = 0;
    int trials = 1000;
    double successProbability = 0.3;
    
    for (int i = 0; i < trials; i++) {
        if (random.randomBool(successProbability)) {
            successCount++;
        }
    }
    
    double actualProbability = static_cast<double>(successCount) / trials;
    std::cout << "期望概率: " << successProbability << std::endl;
    std::cout << "实际概率: " << actualProbability << std::endl;
    
    return 0;
}

📊 数值计算示例

简单数值算法

cpp
#include <iostream>
#include <cmath>
#include <vector>

// 计算平均值
double calculateMean(const std::vector<double>& data) {
    double sum = 0.0;
    for (double value : data) {
        sum += value;
    }
    return sum / data.size();
}

// 计算标准差
double calculateStandardDeviation(const std::vector<double>& data) {
    double mean = calculateMean(data);
    double sumSquaredDiff = 0.0;
    
    for (double value : data) {
        double diff = value - mean;
        sumSquaredDiff += diff * diff;
    }
    
    return std::sqrt(sumSquaredDiff / data.size());
}

// 查找最大值和最小值
std::pair<double, double> findMinMax(const std::vector<double>& data) {
    double minVal = data[0];
    double maxVal = data[0];
    
    for (double value : data) {
        if (value < minVal) minVal = value;
        if (value > maxVal) maxVal = value;
    }
    
    return {minVal, maxVal};
}

int main() {
    std::cout << "=== 数值计算示例 ===" << std::endl;
    
    std::vector<double> data = {1.2, 3.4, 2.1, 4.8, 2.9, 3.7, 1.8, 4.2, 3.1, 2.6};
    
    std::cout << "数据: ";
    for (double value : data) {
        std::cout << value << " ";
    }
    std::cout << std::endl;
    
    // 统计计算
    double mean = calculateMean(data);
    double stdDev = calculateStandardDeviation(data);
    auto [minVal, maxVal] = findMinMax(data);
    
    std::cout << std::fixed << std::setprecision(3);
    std::cout << "平均值: " << mean << std::endl;
    std::cout << "标准差: " << stdDev << std::endl;
    std::cout << "最小值: " << minVal << std::endl;
    std::cout << "最大值: " << maxVal << std::endl;
    std::cout << "范围: " << (maxVal - minVal) << std::endl;
    
    return 0;
}

📋 数值处理最佳实践

数值编程指南

cpp
#include <iostream>
#include <limits>
#include <cmath>

int main() {
    std::cout << "=== 数值编程最佳实践 ===" << std::endl;
    
    // 1. 避免除零错误
    auto safeDivide = [](double a, double b) -> double {
        if (std::abs(b) < std::numeric_limits<double>::epsilon()) {
            std::cout << "警告:除数接近零" << std::endl;
            return std::numeric_limits<double>::infinity();
        }
        return a / b;
    };
    
    std::cout << "10 / 2 = " << safeDivide(10.0, 2.0) << std::endl;
    std::cout << "10 / 0 = " << safeDivide(10.0, 0.0) << std::endl;
    
    // 2. 使用合适的数据类型
    std::cout << "\n=== 选择合适的数据类型 ===" << std::endl;
    
    // 计数用int
    int count = 0;
    
    // 大整数用long long
    long long bigNumber = 1234567890123456LL;
    
    // 精确计算用double
    double precision = 0.123456789;
    
    // 内存敏感场景用float
    float memory_efficient = 3.14f;
    
    std::cout << "count: " << count << std::endl;
    std::cout << "bigNumber: " << bigNumber << std::endl;
    std::cout << "precision: " << precision << std::endl;
    std::cout << "memory_efficient: " << memory_efficient << std::endl;
    
    // 3. 处理溢出
    std::cout << "\n=== 溢出检查 ===" << std::endl;
    
    auto safeMultiply = [](int a, int b) -> long long {
        long long result = static_cast<long long>(a) * b;
        if (result > std::numeric_limits<int>::max()) {
            std::cout << "警告:整数溢出" << std::endl;
        }
        return result;
    };
    
    std::cout << "100000 * 50000 = " << safeMultiply(100000, 50000) << std::endl;
    
    return 0;
}

总结

C++提供了强大的数值处理能力,从基本运算到复杂的数学计算:

核心要点

  • 数值类型:选择合适的整数和浮点类型
  • 数学函数:利用<cmath>库进行数学运算
  • 精度处理:注意浮点数精度和比较方法
  • 类型转换:掌握数值和字符串之间的转换
  • 随机数:使用现代C++的随机数生成器

最佳实践

  • 使用epsilon进行浮点数比较
  • 选择合适的数据类型避免溢出
  • 进行输入验证防止运算错误
  • 使用标准库函数而非自己实现
  • 注意数值计算的精度和性能

良好的数值处理技能是科学计算、图形学、游戏开发等领域的基础。

本站内容仅供学习和研究使用。