You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

原因分析

  1. 精度处理逻辑差异:代码采用连续高精度计算后统一四舍五入的方式,所有中间结果保留double类型的完整精度,最后输出时才截断到两位小数;而预期结果是基于分步四舍五入后再计算的逻辑,即每一步计算后都将结果四舍五入到两位小数,再进行下一步乘法,两种逻辑的累积精度差异导致结果偏差。
  2. 输入验证文案错误: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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.17 13:39:50