|
|
马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
x
引言
在C++编程中,统计并输出数字的个数是一项基础而重要的技能。无论是在数据分析、游戏开发、科学计算还是日常编程任务中,我们经常需要处理各种数字数据,并对其进行统计。本文将从基础语法开始,逐步深入到高级应用,通过详细的代码示例和实际案例,帮助读者全面掌握这一核心技能。
基础语法部分
基本数据类型和变量
在C++中,数字主要分为整数和浮点数两大类。整数类型包括int、short、long和long long,而浮点数类型包括float、double和long double。了解这些基本数据类型是统计数字的第一步。
- #include <iostream>
- int main() {
- // 整数类型
- int a = 10;
- short b = 20;
- long c = 30000;
- long long d = 4000000000;
-
- // 浮点数类型
- float e = 3.14f;
- double f = 2.71828;
- long double g = 1.618033988749895;
-
- // 输出这些数字
- std::cout << "整数: " << a << ", " << b << ", " << c << ", " << d << std::endl;
- std::cout << "浮点数: " << e << ", " << f << ", " << g << std::endl;
-
- return 0;
- }
复制代码
输入输出流
C++使用iostream库进行输入输出操作。std::cin用于输入,std::cout用于输出。下面是一个简单的例子,展示如何从用户输入中读取数字并输出:
- #include <iostream>
- int main() {
- int number;
- std::cout << "请输入一个整数: ";
- std::cin >> number;
- std::cout << "你输入的数字是: " << number << std::endl;
-
- return 0;
- }
复制代码
基本计数方法
最简单的数字统计方法是使用计数器变量。下面是一个示例,统计用户输入的数字个数:
- #include <iostream>
- int main() {
- int count = 0;
- int number;
-
- std::cout << "请输入一系列整数,以任意非数字字符结束: " << std::endl;
-
- while (std::cin >> number) {
- count++;
- }
-
- std::cout << "你输入了 " << count << " 个数字。" << std::endl;
-
- return 0;
- }
复制代码
在这个例子中,我们使用一个while循环和std::cin来读取用户输入的数字。每次成功读取一个数字,计数器count就会增加1。当用户输入非数字字符时,std::cin >> number会返回false,循环结束。
中级应用
数组中的数字统计
在实际编程中,我们经常需要统计数组中的数字个数。下面是一个示例,统计数组中特定数字的出现次数:
- #include <iostream>
- int main() {
- int numbers[] = {1, 2, 3, 4, 5, 2, 3, 2, 1, 6, 7, 8, 2};
- int size = sizeof(numbers) / sizeof(numbers[0]);
- int target = 2;
- int count = 0;
-
- for (int i = 0; i < size; i++) {
- if (numbers[i] == target) {
- count++;
- }
- }
-
- std::cout << "数字 " << target << " 在数组中出现了 " << count << " 次。" << std::endl;
-
- return 0;
- }
复制代码
如果我们想统计数组中所有数字的出现次数,可以使用一个映射(map)来存储每个数字及其出现次数:
- #include <iostream>
- #include <map>
- int main() {
- int numbers[] = {1, 2, 3, 4, 5, 2, 3, 2, 1, 6, 7, 8, 2};
- int size = sizeof(numbers) / sizeof(numbers[0]);
- std::map<int, int> frequency;
-
- for (int i = 0; i < size; i++) {
- frequency[numbers[i]]++;
- }
-
- std::cout << "数字出现频率统计:" << std::endl;
- for (const auto& pair : frequency) {
- std::cout << pair.first << ": " << pair.second << " 次" << std::endl;
- }
-
- return 0;
- }
复制代码
字符串中的数字统计
有时我们需要从字符串中提取并统计数字。下面是一个示例,统计字符串中的数字个数:
- #include <iostream>
- #include <string>
- #include <cctype>
- int main() {
- std::string str = "abc123def456ghi789jkl";
- int count = 0;
-
- for (char c : str) {
- if (isdigit(c)) {
- count++;
- }
- }
-
- std::cout << "字符串 "" << str << "" 中包含 " << count << " 个数字字符。" << std::endl;
-
- return 0;
- }
复制代码
如果我们想提取并统计字符串中的完整数字(而不仅仅是数字字符),可以使用更复杂的方法:
- #include <iostream>
- #include <string>
- #include <vector>
- #include <sstream>
- #include <map>
- int main() {
- std::string str = "abc123def456ghi789jkl0mno42";
- std::vector<int> numbers;
- std::string currentNumber;
-
- for (char c : str) {
- if (isdigit(c)) {
- currentNumber += c;
- } else if (!currentNumber.empty()) {
- std::istringstream iss(currentNumber);
- int number;
- iss >> number;
- numbers.push_back(number);
- currentNumber.clear();
- }
- }
-
- // 处理字符串末尾的数字
- if (!currentNumber.empty()) {
- std::istringstream iss(currentNumber);
- int number;
- iss >> number;
- numbers.push_back(number);
- }
-
- std::cout << "从字符串中提取的数字: ";
- for (int num : numbers) {
- std::cout << num << " ";
- }
- std::cout << std::endl;
-
- std::cout << "共提取了 " << numbers.size() << " 个数字。" << std::endl;
-
- // 统计每个数字的出现频率
- std::map<int, int> frequency;
- for (int num : numbers) {
- frequency[num]++;
- }
-
- std::cout << "数字出现频率统计:" << std::endl;
- for (const auto& pair : frequency) {
- std::cout << pair.first << ": " << pair.second << " 次" << std::endl;
- }
-
- return 0;
- }
复制代码
文件中的数字统计
在实际应用中,我们经常需要从文件中读取数据并统计数字。下面是一个示例,统计文本文件中的数字个数:
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <vector>
- #include <sstream>
- int main() {
- std::ifstream file("numbers.txt");
- if (!file.is_open()) {
- std::cerr << "无法打开文件" << std::endl;
- return 1;
- }
-
- std::vector<int> numbers;
- std::string line;
-
- while (std::getline(file, line)) {
- std::istringstream iss(line);
- int number;
-
- while (iss >> number) {
- numbers.push_back(number);
- }
- }
-
- file.close();
-
- std::cout << "从文件中读取的数字: ";
- for (int num : numbers) {
- std::cout << num << " ";
- }
- std::cout << std::endl;
-
- std::cout << "文件中共有 " << numbers.size() << " 个数字。" << std::endl;
-
- return 0;
- }
复制代码
如果我们想统计文件中每个数字的出现频率,可以使用以下代码:
- #include <iostream>
- #include <fstream>
- #include <string>
- #include <map>
- #include <sstream>
- int main() {
- std::ifstream file("numbers.txt");
- if (!file.is_open()) {
- std::cerr << "无法打开文件" << std::endl;
- return 1;
- }
-
- std::map<int, int> frequency;
- std::string line;
-
- while (std::getline(file, line)) {
- std::istringstream iss(line);
- int number;
-
- while (iss >> number) {
- frequency[number]++;
- }
- }
-
- file.close();
-
- std::cout << "文件中数字出现频率统计:" << std::endl;
- for (const auto& pair : frequency) {
- std::cout << pair.first << ": " << pair.second << " 次" << std::endl;
- }
-
- return 0;
- }
复制代码
高级应用
使用STL容器和算法
C++标准模板库(STL)提供了丰富的容器和算法,可以大大简化数字统计的任务。下面是一些使用STL进行数字统计的示例:
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <numeric>
- int main() {
- std::vector<int> numbers = {1, 2, 3, 4, 5, 2, 3, 2, 1, 6, 7, 8, 2};
-
- // 统计特定数字的出现次数
- int target = 2;
- int count = std::count(numbers.begin(), numbers.end(), target);
- std::cout << "数字 " << target << " 出现了 " << count << " 次。" << std::endl;
-
- // 计算所有数字的总和
- int sum = std::accumulate(numbers.begin(), numbers.end(), 0);
- std::cout << "所有数字的总和是: " << sum << std::endl;
-
- // 计算数字的平均值
- double average = static_cast<double>(sum) / numbers.size();
- std::cout << "数字的平均值是: " << average << std::endl;
-
- // 找出最大值和最小值
- auto [minIt, maxIt] = std::minmax_element(numbers.begin(), numbers.end());
- std::cout << "最小值: " << *minIt << ", 最大值: " << *maxIt << std::endl;
-
- return 0;
- }
复制代码- #include <iostream>
- #include <vector>
- #include <map>
- #include <algorithm>
- int main() {
- std::vector<int> numbers = {1, 2, 3, 4, 5, 2, 3, 2, 1, 6, 7, 8, 2};
- std::map<int, int> frequency;
-
- // 使用for_each和lambda表达式统计频率
- std::for_each(numbers.begin(), numbers.end(),
- [&frequency](int n) { frequency[n]++; });
-
- // 输出频率统计
- std::cout << "数字出现频率统计:" << std::endl;
- for (const auto& pair : frequency) {
- std::cout << pair.first << ": " << pair.second << " 次" << std::endl;
- }
-
- // 找出出现次数最多的数字
- auto mostFrequent = std::max_element(frequency.begin(), frequency.end(),
- [](const auto& a, const auto& b) { return a.second < b.second; });
-
- std::cout << "出现次数最多的数字是 " << mostFrequent->first
- << ",出现了 " << mostFrequent->second << " 次。" << std::endl;
-
- return 0;
- }
复制代码- #include <iostream>
- #include <vector>
- #include <unordered_map>
- #include <algorithm>
- int main() {
- std::vector<int> numbers = {1, 2, 3, 4, 5, 2, 3, 2, 1, 6, 7, 8, 2};
- std::unordered_map<int, int> frequency;
-
- // 统计频率
- for (int num : numbers) {
- frequency[num]++;
- }
-
- // 输出频率统计
- std::cout << "数字出现频率统计:" << std::endl;
- for (const auto& pair : frequency) {
- std::cout << pair.first << ": " << pair.second << " 次" << std::endl;
- }
-
- // 按频率排序
- std::vector<std::pair<int, int>> sortedFrequency(frequency.begin(), frequency.end());
- std::sort(sortedFrequency.begin(), sortedFrequency.end(),
- [](const auto& a, const auto& b) { return a.second > b.second; });
-
- // 输出排序后的频率统计
- std::cout << "\n按频率排序后的统计:" << std::endl;
- for (const auto& pair : sortedFrequency) {
- std::cout << pair.first << ": " << pair.second << " 次" << std::endl;
- }
-
- return 0;
- }
复制代码
多种数据类型的数字统计
在实际应用中,我们可能需要处理多种数据类型的数字。下面是一个示例,统计不同类型数字的出现次数:
- #include <iostream>
- #include <vector>
- #include <variant>
- #include <map>
- #include <string>
- #include <iomanip>
- // 使用std::variant来处理多种数字类型
- using NumberType = std::variant<int, float, double, long>;
- // 访问者模式,用于打印不同类型的数字
- struct PrintVisitor {
- void operator()(int i) const { std::cout << i << " (int)"; }
- void operator()(float f) const { std::cout << std::fixed << std::setprecision(2) << f << " (float)"; }
- void operator()(double d) const { std::cout << std::fixed << std::setprecision(4) << d << " (double)"; }
- void operator()(long l) const { std::cout << l << " (long)"; }
- };
- // 访问者模式,用于获取数字类型的字符串表示
- struct TypeVisitor {
- std::string operator()(int) const { return "int"; }
- std::string operator()(float) const { return "float"; }
- std::string operator()(double) const { return "double"; }
- std::string operator()(long) const { return "long"; }
- };
- int main() {
- std::vector<NumberType> numbers = {
- 1, 2.5f, 3.14159, 4L, 5, 6.7f, 8.90123, 10L, 11, 12.3f
- };
-
- // 按类型统计数字个数
- std::map<std::string, int> typeCount;
-
- for (const auto& num : numbers) {
- std::string type = std::visit(TypeVisitor{}, num);
- typeCount[type]++;
- }
-
- // 输出类型统计
- std::cout << "按类型统计数字个数:" << std::endl;
- for (const auto& pair : typeCount) {
- std::cout << pair.first << ": " << pair.second << " 个" << std::endl;
- }
-
- // 输出所有数字及其类型
- std::cout << "\n所有数字及其类型:" << std::endl;
- for (const auto& num : numbers) {
- std::visit(PrintVisitor{}, num);
- std::cout << std::endl;
- }
-
- return 0;
- }
复制代码
性能优化技巧
在处理大量数据时,性能优化变得尤为重要。下面是一些优化数字统计性能的技巧:
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <execution>
- #include <chrono>
- #include <random>
- int main() {
- // 生成大量随机数
- const int size = 10000000;
- std::vector<int> numbers(size);
-
- std::random_device rd;
- std::mt19937 gen(rd());
- std::uniform_int_distribution<> dis(1, 100);
-
- for (int i = 0; i < size; i++) {
- numbers[i] = dis(gen);
- }
-
- // 使用顺序算法统计特定数字的出现次数
- int target = 42;
- auto start = std::chrono::high_resolution_clock::now();
- int countSeq = std::count(numbers.begin(), numbers.end(), target);
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double> seqTime = end - start;
-
- std::cout << "顺序算法结果: " << countSeq << std::endl;
- std::cout << "顺序算法耗时: " << seqTime.count() << " 秒" << std::endl;
-
- // 使用并行算法统计特定数字的出现次数
- start = std::chrono::high_resolution_clock::now();
- int countPar = std::count(std::execution::par, numbers.begin(), numbers.end(), target);
- end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double> parTime = end - start;
-
- std::cout << "并行算法结果: " << countPar << std::endl;
- std::cout << "并行算法耗时: " << parTime.count() << " 秒" << std::endl;
-
- std::cout << "并行算法比顺序算法快 " << (seqTime.count() / parTime.count()) << " 倍" << std::endl;
-
- return 0;
- }
复制代码- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <random>
- // 使用位运算统计特定数字的出现次数
- int countWithBitOps(const std::vector<int>& numbers, int target) {
- int count = 0;
- for (int num : numbers) {
- // 使用异或运算和比较,避免分支预测
- count += ((num ^ target) - 1) >> 31 & 1;
- }
- return count;
- }
- int main() {
- // 生成大量随机数
- const int size = 10000000;
- std::vector<int> numbers(size);
-
- std::random_device rd;
- std::mt19937 gen(rd());
- std::uniform_int_distribution<> dis(1, 100);
-
- for (int i = 0; i < size; i++) {
- numbers[i] = dis(gen);
- }
-
- int target = 42;
-
- // 使用标准算法
- auto start = std::chrono::high_resolution_clock::now();
- int countStd = std::count(numbers.begin(), numbers.end(), target);
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double> stdTime = end - start;
-
- // 使用位运算优化
- start = std::chrono::high_resolution_clock::now();
- int countBit = countWithBitOps(numbers, target);
- end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double> bitTime = end - start;
-
- std::cout << "标准算法结果: " << countStd << std::endl;
- std::cout << "标准算法耗时: " << stdTime.count() << " 秒" << std::endl;
-
- std::cout << "位运算算法结果: " << countBit << std::endl;
- std::cout << "位运算算法耗时: " << bitTime.count() << " 秒" << std::endl;
-
- std::cout << "位运算算法比标准算法快 " << (stdTime.count() / bitTime.count()) << " 倍" << std::endl;
-
- return 0;
- }
复制代码- #include <iostream>
- #include <vector>
- #include <unordered_map>
- #include <random>
- #include <chrono>
- // 使用连续内存的向量代替哈希表进行频率统计
- std::vector<int> countWithVector(const std::vector<int>& numbers, int maxVal) {
- std::vector<int> frequency(maxVal + 1, 0);
-
- for (int num : numbers) {
- if (num >= 0 && num <= maxVal) {
- frequency[num]++;
- }
- }
-
- return frequency;
- }
- // 使用哈希表进行频率统计
- std::unordered_map<int, int> countWithUnorderedMap(const std::vector<int>& numbers) {
- std::unordered_map<int, int> frequency;
-
- for (int num : numbers) {
- frequency[num]++;
- }
-
- return frequency;
- }
- int main() {
- // 生成大量随机数
- const int size = 10000000;
- std::vector<int> numbers(size);
-
- std::random_device rd;
- std::mt19937 gen(rd());
- std::uniform_int_distribution<> dis(1, 1000);
-
- for (int i = 0; i < size; i++) {
- numbers[i] = dis(gen);
- }
-
- // 使用向量进行频率统计
- auto start = std::chrono::high_resolution_clock::now();
- auto frequencyVec = countWithVector(numbers, 1000);
- auto end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double> vecTime = end - start;
-
- // 使用哈希表进行频率统计
- start = std::chrono::high_resolution_clock::now();
- auto frequencyMap = countWithUnorderedMap(numbers);
- end = std::chrono::high_resolution_clock::now();
- std::chrono::duration<double> mapTime = end - start;
-
- std::cout << "向量统计耗时: " << vecTime.count() << " 秒" << std::endl;
- std::cout << "哈希表统计耗时: " << mapTime.count() << " 秒" << std::endl;
-
- std::cout << "向量统计比哈希表统计快 " << (mapTime.count() / vecTime.count()) << " 倍" << std::endl;
-
- return 0;
- }
复制代码
实际案例分析
数据分析中的数字统计
在数据分析中,我们经常需要统计各种数字指标,如平均值、中位数、众数等。下面是一个示例,展示如何使用C++进行基本的数据分析:
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <numeric>
- #include <map>
- #include <iomanip>
- #include <random>
- class DataAnalyzer {
- private:
- std::vector<double> data;
-
- public:
- DataAnalyzer(const std::vector<double>& input) : data(input) {}
-
- // 计算平均值
- double mean() const {
- if (data.empty()) return 0.0;
- return std::accumulate(data.begin(), data.end(), 0.0) / data.size();
- }
-
- // 计算中位数
- double median() {
- if (data.empty()) return 0.0;
-
- std::sort(data.begin(), data.end());
-
- size_t size = data.size();
- if (size % 2 == 0) {
- return (data[size/2 - 1] + data[size/2]) / 2.0;
- } else {
- return data[size/2];
- }
- }
-
- // 计算众数
- std::vector<double> modes() {
- if (data.empty()) return {};
-
- std::map<double, int> frequency;
- for (double value : data) {
- frequency[value]++;
- }
-
- int maxFreq = 0;
- for (const auto& pair : frequency) {
- if (pair.second > maxFreq) {
- maxFreq = pair.second;
- }
- }
-
- std::vector<double> result;
- for (const auto& pair : frequency) {
- if (pair.second == maxFreq) {
- result.push_back(pair.first);
- }
- }
-
- return result;
- }
-
- // 计算标准差
- double standardDeviation() const {
- if (data.size() < 2) return 0.0;
-
- double m = mean();
- double sqSum = std::inner_product(data.begin(), data.end(), data.begin(), 0.0);
- return std::sqrt(sqSum / data.size() - m * m);
- }
-
- // 计算四分位数
- std::vector<double> quartiles() {
- if (data.empty()) return {0.0, 0.0, 0.0};
-
- std::sort(data.begin(), data.end());
-
- size_t n = data.size();
- double q1, q2, q3;
-
- // 计算Q2(中位数)
- if (n % 2 == 0) {
- q2 = (data[n/2 - 1] + data[n/2]) / 2.0;
- } else {
- q2 = data[n/2];
- }
-
- // 计算Q1
- size_t m = n / 2;
- if (m % 2 == 0) {
- q1 = (data[m/2 - 1] + data[m/2]) / 2.0;
- } else {
- q1 = data[m/2];
- }
-
- // 计算Q3
- if (n % 2 == 0) {
- if (m % 2 == 0) {
- q3 = (data[m + m/2 - 1] + data[m + m/2]) / 2.0;
- } else {
- q3 = data[m + m/2];
- }
- } else {
- if (m % 2 == 0) {
- q3 = (data[m + 1 + m/2 - 1] + data[m + 1 + m/2]) / 2.0;
- } else {
- q3 = data[m + 1 + m/2];
- }
- }
-
- return {q1, q2, q3};
- }
-
- // 生成统计报告
- void generateReport() {
- std::cout << std::fixed << std::setprecision(2);
- std::cout << "数据统计报告:" << std::endl;
- std::cout << "--------------------------------" << std::endl;
- std::cout << "数据点数量: " << data.size() << std::endl;
- std::cout << "平均值: " << mean() << std::endl;
- std::cout << "中位数: " << median() << std::endl;
-
- auto modeValues = modes();
- if (modeValues.size() == 1) {
- std::cout << "众数: " << modeValues[0] << std::endl;
- } else {
- std::cout << "众数: ";
- for (size_t i = 0; i < modeValues.size(); i++) {
- if (i > 0) std::cout << ", ";
- std::cout << modeValues[i];
- }
- std::cout << std::endl;
- }
-
- std::cout << "标准差: " << standardDeviation() << std::endl;
-
- auto qs = quartiles();
- std::cout << "四分位数: Q1=" << qs[0] << ", Q2=" << qs[1] << ", Q3=" << qs[2] << std::endl;
- std::cout << "--------------------------------" << std::endl;
- }
- };
- int main() {
- // 生成随机数据
- const int size = 100;
- std::vector<double> data(size);
-
- std::random_device rd;
- std::mt19937 gen(rd());
- std::normal_distribution<> dist(50.0, 15.0); // 正态分布,均值50,标准差15
-
- for (int i = 0; i < size; i++) {
- data[i] = dist(gen);
- }
-
- // 创建数据分析器并生成报告
- DataAnalyzer analyzer(data);
- analyzer.generateReport();
-
- return 0;
- }
复制代码
游戏开发中的数字统计
在游戏开发中,数字统计可以用于各种目的,如计分、统计玩家行为、分析游戏数据等。下面是一个简单的游戏统计系统示例:
- #include <iostream>
- #include <vector>
- #include <map>
- #include <string>
- #include <algorithm>
- #include <random>
- #include <ctime>
- class GameStats {
- private:
- std::map<std::string, int> playerScores;
- std::map<int, int> levelCompletionTimes; // 关卡ID -> 完成时间(秒)
- std::map<std::string, int> itemUsage; // 物品名称 -> 使用次数
- std::vector<int> dailyActivePlayers; // 每日活跃玩家数
-
- public:
- // 添加玩家分数
- void addPlayerScore(const std::string& playerName, int score) {
- playerScores[playerName] += score;
- }
-
- // 记录关卡完成时间
- void recordLevelCompletion(int levelId, int timeInSeconds) {
- levelCompletionTimes[levelId] = timeInSeconds;
- }
-
- // 记录物品使用
- void recordItemUsage(const std::string& itemName) {
- itemUsage[itemName]++;
- }
-
- // 记录每日活跃玩家数
- void recordDailyActivePlayers(int count) {
- dailyActivePlayers.push_back(count);
- }
-
- // 获取排行榜
- std::vector<std::pair<std::string, int>> getLeaderboard(int topN = 10) {
- std::vector<std::pair<std::string, int>> sortedPlayers(
- playerScores.begin(), playerScores.end());
-
- std::sort(sortedPlayers.begin(), sortedPlayers.end(),
- [](const auto& a, const auto& b) { return a.second > b.second; });
-
- if (sortedPlayers.size() > static_cast<size_t>(topN)) {
- sortedPlayers.resize(topN);
- }
-
- return sortedPlayers;
- }
-
- // 获取平均关卡完成时间
- double getAverageLevelCompletionTime() const {
- if (levelCompletionTimes.empty()) return 0.0;
-
- double sum = 0.0;
- for (const auto& pair : levelCompletionTimes) {
- sum += pair.second;
- }
-
- return sum / levelCompletionTimes.size();
- }
-
- // 获取最常用的物品
- std::vector<std::pair<std::string, int>> getMostUsedItems(int topN = 5) {
- std::vector<std::pair<std::string, int>> sortedItems(
- itemUsage.begin(), itemUsage.end());
-
- std::sort(sortedItems.begin(), sortedItems.end(),
- [](const auto& a, const auto& b) { return a.second > b.second; });
-
- if (sortedItems.size() > static_cast<size_t>(topN)) {
- sortedItems.resize(topN);
- }
-
- return sortedItems;
- }
-
- // 获取平均每日活跃玩家数
- double getAverageDailyActivePlayers() const {
- if (dailyActivePlayers.empty()) return 0.0;
-
- double sum = 0.0;
- for (int count : dailyActivePlayers) {
- sum += count;
- }
-
- return sum / dailyActivePlayers.size();
- }
-
- // 生成统计报告
- void generateReport() {
- std::cout << "游戏统计报告" << std::endl;
- std::cout << "==========================" << std::endl;
-
- // 排行榜
- std::cout << "\n玩家排行榜 (前5名):" << std::endl;
- auto leaderboard = getLeaderboard(5);
- for (size_t i = 0; i < leaderboard.size(); i++) {
- std::cout << (i+1) << ". " << leaderboard[i].first
- << ": " << leaderboard[i].second << " 分" << std::endl;
- }
-
- // 关卡完成时间
- std::cout << "\n关卡统计:" << std::endl;
- std::cout << "平均关卡完成时间: " << getAverageLevelCompletionTime() << " 秒" << std::endl;
- std::cout << "总关卡数: " << levelCompletionTimes.size() << std::endl;
-
- // 物品使用
- std::cout << "\n最常用物品 (前3名):" << std::endl;
- auto topItems = getMostUsedItems(3);
- for (size_t i = 0; i < topItems.size(); i++) {
- std::cout << (i+1) << ". " << topItems[i].first
- << ": " << topItems[i].second << " 次" << std::endl;
- }
-
- // 每日活跃玩家
- std::cout << "\n玩家活跃度:" << std::endl;
- std::cout << "平均每日活跃玩家数: " << getAverageDailyActivePlayers() << std::endl;
- std::cout << "记录天数: " << dailyActivePlayers.size() << std::endl;
-
- std::cout << "\n==========================" << std::endl;
- }
- };
- int main() {
- // 创建游戏统计对象
- GameStats stats;
-
- // 模拟游戏数据
- std::vector<std::string> playerNames = {"Alice", "Bob", "Charlie", "David", "Eve", "Frank", "Grace"};
- std::vector<std::string> itemNames = {"Health Potion", "Mana Potion", "Sword", "Shield", "Bow"};
-
- std::random_device rd;
- std::mt19937 gen(rd());
-
- // 模拟玩家分数
- std::uniform_int_distribution<> scoreDist(100, 1000);
- for (int i = 0; i < 50; i++) {
- std::string player = playerNames[gen() % playerNames.size()];
- int score = scoreDist(gen);
- stats.addPlayerScore(player, score);
- }
-
- // 模拟关卡完成时间
- std::uniform_int_distribution<> levelDist(1, 10);
- std::uniform_int_distribution<> timeDist(60, 600);
- for (int i = 0; i < 30; i++) {
- int level = levelDist(gen);
- int time = timeDist(gen);
- stats.recordLevelCompletion(level, time);
- }
-
- // 模拟物品使用
- std::uniform_int_distribution<> itemDist(0, itemNames.size() - 1);
- for (int i = 0; i < 100; i++) {
- std::string item = itemNames[itemDist(gen)];
- stats.recordItemUsage(item);
- }
-
- // 模拟每日活跃玩家
- std::uniform_int_distribution<> playerDist(50, 200);
- for (int i = 0; i < 30; i++) {
- int count = playerDist(gen);
- stats.recordDailyActivePlayers(count);
- }
-
- // 生成统计报告
- stats.generateReport();
-
- return 0;
- }
复制代码
科学计算中的数字统计
在科学计算中,数字统计是数据分析的基础。下面是一个示例,展示如何使用C++进行科学数据的统计分析:
- #include <iostream>
- #include <vector>
- #include <algorithm>
- #include <numeric>
- #include <cmath>
- #include <iomanip>
- #include <random>
- class ScientificDataAnalyzer {
- private:
- std::vector<double> data;
-
- public:
- ScientificDataAnalyzer(const std::vector<double>& input) : data(input) {}
-
- // 基本统计量
- double mean() const {
- if (data.empty()) return 0.0;
- return std::accumulate(data.begin(), data.end(), 0.0) / data.size();
- }
-
- double median() {
- if (data.empty()) return 0.0;
-
- std::sort(data.begin(), data.end());
-
- size_t size = data.size();
- if (size % 2 == 0) {
- return (data[size/2 - 1] + data[size/2]) / 2.0;
- } else {
- return data[size/2];
- }
- }
-
- double variance() const {
- if (data.size() < 2) return 0.0;
-
- double m = mean();
- double sum = 0.0;
- for (double value : data) {
- sum += (value - m) * (value - m);
- }
-
- return sum / (data.size() - 1); // 样本方差
- }
-
- double standardDeviation() const {
- return std::sqrt(variance());
- }
-
- // 偏度和峰度
- double skewness() const {
- if (data.size() < 3) return 0.0;
-
- double m = mean();
- double s = standardDeviation();
-
- if (s == 0.0) return 0.0;
-
- double sum = 0.0;
- for (double value : data) {
- double z = (value - m) / s;
- sum += z * z * z;
- }
-
- return sum / data.size();
- }
-
- double kurtosis() const {
- if (data.size() < 4) return 0.0;
-
- double m = mean();
- double s = standardDeviation();
-
- if (s == 0.0) return 0.0;
-
- double sum = 0.0;
- for (double value : data) {
- double z = (value - m) / s;
- sum += z * z * z * z;
- }
-
- return sum / data.size() - 3.0; // 超出峰度
- }
-
- // 百分位数
- double percentile(double p) {
- if (data.empty() || p < 0.0 || p > 100.0) return 0.0;
-
- std::sort(data.begin(), data.end());
-
- double n = data.size();
- double pos = p * (n - 1) / 100.0;
- int k = static_cast<int>(pos);
- double d = pos - k;
-
- if (k + 1 < static_cast<int>(n)) {
- return data[k] + d * (data[k + 1] - data[k]);
- } else {
- return data[k];
- }
- }
-
- // 直方图
- std::vector<int> histogram(int bins) {
- if (data.empty() || bins <= 0) return {};
-
- auto [minIt, maxIt] = std::minmax_element(data.begin(), data.end());
- double minVal = *minIt;
- double maxVal = *maxIt;
-
- if (minVal == maxVal) return std::vector<int>(bins, static_cast<int>(data.size()));
-
- double binWidth = (maxVal - minVal) / bins;
- std::vector<int> hist(bins, 0);
-
- for (double value : data) {
- int binIndex = static_cast<int>((value - minVal) / binWidth);
- if (binIndex >= bins) binIndex = bins - 1; // 处理最大值
- hist[binIndex]++;
- }
-
- return hist;
- }
-
- // 相关性
- double correlation(const std::vector<double>& other) const {
- if (data.size() != other.size() || data.empty()) return 0.0;
-
- double meanX = mean();
- double meanY = std::accumulate(other.begin(), other.end(), 0.0) / other.size();
-
- double numerator = 0.0;
- double sumSqX = 0.0;
- double sumSqY = 0.0;
-
- for (size_t i = 0; i < data.size(); i++) {
- double devX = data[i] - meanX;
- double devY = other[i] - meanY;
-
- numerator += devX * devY;
- sumSqX += devX * devX;
- sumSqY += devY * devY;
- }
-
- double denominator = std::sqrt(sumSqX * sumSqY);
- if (denominator == 0.0) return 0.0;
-
- return numerator / denominator;
- }
-
- // 生成统计报告
- void generateReport() {
- std::cout << std::fixed << std::setprecision(4);
- std::cout << "科学数据统计分析报告" << std::endl;
- std::cout << "======================================" << std::endl;
- std::cout << "样本数量: " << data.size() << std::endl;
- std::cout << "平均值: " << mean() << std::endl;
- std::cout << "中位数: " << median() << std::endl;
- std::cout << "方差: " << variance() << std::endl;
- std::cout << "标准差: " << standardDeviation() << std::endl;
- std::cout << "偏度: " << skewness() << std::endl;
- std::cout << "峰度: " << kurtosis() << std::endl;
-
- std::cout << "\n百分位数:" << std::endl;
- std::cout << "最小值: " << percentile(0) << std::endl;
- std::cout << "25%: " << percentile(25) << std::endl;
- std::cout << "50% (中位数): " << percentile(50) << std::endl;
- std::cout << "75%: " << percentile(75) << std::endl;
- std::cout << "最大值: " << percentile(100) << std::endl;
-
- // 直方图
- int bins = 10;
- auto hist = histogram(bins);
- std::cout << "\n直方图 (" << bins << " 个区间):" << std::endl;
-
- auto [minIt, maxIt] = std::minmax_element(data.begin(), data.end());
- double minVal = *minIt;
- double maxVal = *maxIt;
- double binWidth = (maxVal - minVal) / bins;
-
- int maxCount = *std::max_element(hist.begin(), hist.end());
- int maxStars = 50;
-
- for (int i = 0; i < bins; i++) {
- double lower = minVal + i * binWidth;
- double upper = lower + binWidth;
-
- std::cout << "[" << std::fixed << std::setprecision(2) << lower
- << ", " << upper << "): ";
-
- int stars = (hist[i] * maxStars) / maxCount;
- for (int j = 0; j < stars; j++) {
- std::cout << "*";
- }
-
- std::cout << " (" << hist[i] << ")" << std::endl;
- }
-
- std::cout << "======================================" << std::endl;
- }
- };
- int main() {
- // 生成测试数据 - 正态分布
- const int size = 1000;
- std::vector<double> data(size);
-
- std::random_device rd;
- std::mt19937 gen(rd());
- std::normal_distribution<> dist(100.0, 15.0);
-
- for (int i = 0; i < size; i++) {
- data[i] = dist(gen);
- }
-
- // 创建分析器并生成报告
- ScientificDataAnalyzer analyzer(data);
- analyzer.generateReport();
-
- // 测试相关性
- std::vector<double> data2(size);
- for (int i = 0; i < size; i++) {
- // 创建与data有线性关系的数据
- data2[i] = 2.0 * data[i] + 10.0 + (dist(gen) - 100.0) * 0.5;
- }
-
- double corr = analyzer.correlation(data2);
- std::cout << "\n两组数据的相关系数: " << corr << std::endl;
-
- return 0;
- }
复制代码
总结与展望
本文从基础语法到高级应用,全面介绍了如何在C++中精确统计并高效输出数字的个数。我们学习了:
1. 基础语法:基本数据类型、输入输出流和基本计数方法。
2. 中级应用:数组、字符串和文件中的数字统计。
3. 高级应用:使用STL容器和算法、多种数据类型的数字统计以及性能优化技巧。
4. 实际案例分析:数据分析、游戏开发和科学计算中的数字统计应用。
通过这些内容,读者应该能够掌握C++中数字统计的核心技能,并能够将其应用到实际项目中。
随着C++标准的不断发展,我们有理由相信未来会有更多强大的工具和库来支持数字统计和数据分析。例如,C++20引入的范围库(Ranges)和概念(Concepts)将进一步简化数据处理的代码。此外,随着并行计算和GPU编程的普及,我们也将看到更多高效的数字统计算法的出现。
无论你是初学者还是有经验的开发者,掌握数字统计这一核心技能都将对你的编程之路产生积极影响。希望本文能够帮助你更好地理解和应用C++中的数字统计技术。 |
|