C++能耗计算器异常:日/周/月费用结果低于预期求助
C++版Meralco能耗计算器计算偏差排查与修复
问题描述
开发的C++版Meralco能耗计算器存在计算异常:小时费用计算结果正确,但日、周、月费用结果始终低于预期值。
核心计算代码片段
const double FACTOR_RATE = 0.0097822; // PHP per watt-hour case 1: watts = 3950; applianceName = "A/C Floor Stand non inverter 4.5 HP"; cout << "You chose 1. A/C Floor Stand non inverter 4.5HP 3950 watts" << endl; break; costPerHour = watts * FACTOR_RATE; // PHP per hour costPerDay = costPerHour * hoursPerDay; // PHP per day costPerWeek = costPerDay * daysPerWeek; // PHP per week costPerMonth = costPerWeek * weeksPerMonth; // PHP per month
完整代码
#include <iostream> #include <iomanip> #include <string> #include <limits> // For numeric_limits using namespace std; // Function to validate integer input within a specific range int validateInput(int min, int max, const string& prompt) { int value; while (true) { cout << prompt; cin >> value; // Check for input failure (e.g., non-integer input) if (cin.fail()) { cin.clear(); // Clear the error flag cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Discard invalid input cout << "Invalid input. Please enter an integer value." << endl; continue; } // Check if the input is within the valid range if (value < min || value > max) { cout << "Invalid input. Please enter a value between " << min << " and " << max << "." << endl; continue; } // Valid input cin.ignore(numeric_limits<streamsize>::max(), '\n'); // Discard any remaining input return value; } } int main() { // Constants const double FACTOR_RATE = 0.0097822; // PHP per watt-hour // Variables for login string username, password; // Variables for menu choices char mainChoice; int categoryChoice; // Variables for appliance details double watts = 0.0; string applianceName = ""; // Variables for usage inputs int hoursPerDay, daysPerWeek, weeksPerMonth; // Variables for cost calculations double costPerHour, costPerDay, costPerWeek, costPerMonth; // ------------------------------ // Simple Login Section // ------------------------------ cout << "Welcome to Meralco Electricity Calculator" << endl; cout << "Log In" << endl; cout << "Enter your username: "; cin >> username; cout << "Enter your password: "; cin >> password; cout << "-----------------------------" << endl; cout << "Hello, " << username << "!" << endl << endl; // ------------------------------ // Main Menu Section // ------------------------------ cout << "To begin the calculation, choose one of the categories below." << endl; cout << "A. Airconditioner" << endl; cout << "B. Computer and Gadgets" << endl; cout << "C. Kitchen Appliances" << endl; cout << "Enter your choice (A/B/C): "; cin >> mainChoice; cout << endl; // Convert mainChoice to uppercase for consistency mainChoice = toupper(mainChoice); // ------------------------------ // Category Selection Section // ------------------------------ switch (mainChoice) { case 'A': cout << "You chose Airconditioner" << endl; cout << "1. A/C Floor Stand non inverter 4.5HP 3950 watts" << endl; cout << "2. A/C Floor Split type inverter 1.00 HP 800 watts" << endl; cout << "3. A/C Floor Split type inverter 1.50 HP 1100 watts" << endl; cout << "4. A/C Floor Split type inverter 2.0 HP 1500 watts" << endl; cout << "5. A/C Floor Split type inverter 2.50HP 2300 watts" << endl; cout << "Enter the airconditioner category (1-5): "; cin >> categoryChoice; cout << endl; switch (categoryChoice) { case 1: watts = 3950; applianceName = "A/C Floor Stand non inverter 4.5 HP"; cout << "You chose 1. A/C Floor Stand non inverter 4.5HP 3950 watts" << endl; break; case 2: watts = 800; applianceName = "A/C Floor Split type inverter 1.00 HP"; cout << "You chose 2. A/C Floor Split type inverter 1.00 HP 800 watts" << endl; break; case 3: watts = 1100; applianceName = "A/C Floor Split type inverter 1.50 HP"; cout << "You chose 3. A/C Floor Split type inverter 1.50 HP 1100 watts" << endl; break; case 4: watts = 1500; applianceName = "A/C Floor Split type inverter 2.0 HP"; cout << "You chose 4. A/C Floor Split type inverter 2.0 HP 1500 watts" << endl; break; case 5: watts = 2300; applianceName = "A/C Floor Split type inverter 2.50HP"; cout << "You chose 5. A/C Floor Split type inverter 2.50HP 2300 watts" << endl; break; default: cout << "Enter correct number." << endl; return 0; } break; case 'B': cout << "You chose Computer and Gadgets" << endl; cout << "1. Printer 478 watts" << endl; cout << "2. Router 110 watts" << endl; cout << "3. Scanner 11 watts" << endl; cout << "4. Laptop 60 watts" << endl; cout << "5. Desktop Standard 65 watts" << endl; cout << "Enter the computer or gadget category (1-5): "; cin >> categoryChoice; cout << endl; switch (categoryChoice) { case 1: watts = 478; applianceName = "Printer"; cout << "You chose 1. Printer 478 watts" << endl; break; case 2: watts = 110; applianceName = "Router"; cout << "You chose 2. Router 110 watts" << endl; break; case 3: watts = 11; applianceName = "Scanner"; cout << "You chose 3. Scanner 11 watts" << endl; break; case 4: watts = 60; applianceName = "Laptop"; cout << "You chose 4. Laptop 60 watts" << endl; break; case 5: watts = 65; applianceName = "Desktop Standard"; cout << "You chose 5. Desktop Standard 65 watts" << endl; break; default: cout << "Enter correct number." << endl; return 0; } break; case 'C': cout << "You chose Kitchen Appliances" << endl; cout << "1. Induction cooker 1500 watts" << endl; cout << "2. Refrigerator French 193 watts" << endl; cout << "3. Rice cooker 3L 1000 watts" << endl; cout << "4. Washing Machine FrontLoad 2000 watts" << endl; cout << "5. Smart LED 15 watts" << endl; cout << "Enter the kitchen appliance category (1-5): "; cin >> categoryChoice; cout << endl; switch (categoryChoice) { case 1: watts = 1500; applianceName = "Induction cooker"; cout << "You chose 1. Induction cooker 1500 watts" << endl; break; case 2: watts = 193; applianceName = "Refrigerator French"; cout << "You chose 2. Refrigerator French 193 watts" << endl; break; case 3: watts = 1000; applianceName = "Rice cooker 3L"; cout << "You chose 3. Rice cooker 3L 1000 watts" << endl; break; case 4: watts = 2000; applianceName = "Washing Machine FrontLoad"; cout << "You chose 4. Washing Machine FrontLoad 2000 watts" << endl; break; case 5: watts = 15; applianceName = "Smart LED"; cout << "You chose 5. Smart LED 15 watts" << endl; break; default: cout << "Enter correct number." << endl; return 0; } break; default: cout << "Enter correct number." << endl; return 0; } cout << "-----------------------------" << endl; // ------------------------------ // Input Usage Details Section // ------------------------------ // Validate hours per day (0-24) hoursPerDay = validateInput(0, 24, "Enter the number of hours used per day: "); // Validate days per week (1-7) daysPerWeek = validateInput(1, 7, "Enter the number of days used per week (1-7): "); // Validate weeks per month (1-4) weeksPerMonth = validateInput(1, 4, "Enter the number of weeks used per month (1-5): "); cout << "-----------------------------" << endl << endl; // ------------------------------ // Cost Calculation Section // ------------------------------ // Calculate cost based on watt-hours costPerHour = watts * FACTOR_RATE; // PHP per hour costPerDay = costPerHour * hoursPerDay; // PHP per day costPerWeek = costPerDay * daysPerWeek; // PHP per week costPerMonth = costPerWeek * weeksPerMonth; // PHP per month // ------------------------------ // Output Results Section // ------------------------------ cout << fixed << setprecision(2); cout << "Appliance: " << applianceName << endl; cout << "Wattage: " << watts << " watts" << endl; cout << "Usage: " << hoursPerDay << " hours/day for " << daysPerWeek << " days/week and " << weeksPerMonth << " weeks/month" << endl; cout << "-----------------------------" << endl; cout << "Cost per hour: PHP " << costPerHour << endl; cout << "Cost per day: PHP " << costPerDay << endl; cout << "Cost per week: PHP " << costPerWeek << endl; cout << "Cost per month: PHP " << costPerMonth << endl; return 0; }
测试用例
- 电器:A/C Floor Stand non inverter 4.5HP 3950 watts
- 每日使用时长:6小时
- 每周使用天数:7天
- 每月使用周数:4周
实际输出
Hour: 38.64 // 唯一正确结果 Day: 231.84 Week: 1622.87 Month: 6491.47
预期输出
Hour: 38.64 Day: 231.87 Week: 1623.06 Month: 6492.24
原因分析
- 精度处理逻辑差异:代码采用连续高精度计算后统一四舍五入的方式,所有中间结果保留
double类型的完整精度,最后输出时才截断到两位小数;而预期结果是基于分步四舍五入后再计算的逻辑,即每一步计算后都将结果四舍五入到两位小数,再进行下一步乘法,两种逻辑的累积精度差异导致结果偏差。 - 输入验证文案错误:
weeksPerMonth的验证范围是1-4,但提示文字写的是(1-5),属于文案不一致问题,不影响当前测试,但需要修正。
修复方案
方案1:匹配分步四舍五入的预期逻辑
如果需要和预期结果一致,需在每一步计算后对结果进行四舍五入到两位小数,使用round()函数(需包含<cmath>头文件):
// 新增头文件 #include <cmath> // 替换原计算代码 costPerHour = round(watts * FACTOR_RATE * 100) / 100; // PHP per hour costPerDay = round(costPerHour * hoursPerDay * 100) / 100; // PHP per day costPerWeek = round(costPerDay * daysPerWeek * 100) / 100; // PHP per week costPerMonth = round(costPerWeek * weeksPerMonth * 100) / 100; // PHP per month
方案2:修正输入验证文案
将weeksPerMonth的提示文字与验证范围统一:
weeksPerMonth = validateInput(1, 4, "Enter the number of weeks used per month (1-4): ");
说明
- 方案1的分步四舍五入会引入累积误差,这也是预期结果与精确计算结果存在差异的原因;而代码原有的连续高精度计算逻辑是更准确的能耗计算方式。
- 若需完全匹配预期值,需确认手动计算时的精度处理规则,再调整代码逻辑。
内容的提问来源于stack exchange,提问作者Yuta Ruitzu
相关产品推荐
相关产品推荐

