C++ 输出为6.9531e-308或0(noob)

C++ 输出为6.9531e-308或0(noob),c++,string,c++11,C++,String,C++11,我正在尝试编写一个程序,根据通话开始/结束的时间以及通话所需的时间来计算通话费用。一切正常,但当它试图实际显示每次通话的成本和最后的总成本时除外 每项费用列为6.9531e-308美元。有人通过将相关变量初始化为零来解决问题,但当我这样做时,程序开始将每个成本列为$0 我计算总数的方法似乎也不起作用,因为当成本为6.9531e-308美元时,总数为7.64841e-307美元,而不是4.17186e-307美元。它要么将其中一个成本乘以11,要么认为有11个成本需要加起来 代码如下: #incl

我正在尝试编写一个程序,根据通话开始/结束的时间以及通话所需的时间来计算通话费用。一切正常,但当它试图实际显示每次通话的成本和最后的总成本时除外

每项费用列为6.9531e-308美元。有人通过将相关变量初始化为零来解决问题,但当我这样做时,程序开始将每个成本列为$0

我计算总数的方法似乎也不起作用,因为当成本为6.9531e-308美元时,总数为7.64841e-307美元,而不是4.17186e-307美元。它要么将其中一个成本乘以11,要么认为有11个成本需要加起来

代码如下:

#include <fstream>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <string>
#include <cstring>

using namespace std;

ifstream fin("call_history.txt"); //read from a file

//int main
int main() {

    string temp;
    double total = 0.0;

    while (getline(fin, temp)) {
        istringstream s(temp);
        string token[3];
        int i = 0;

        while(getline(s, token[i], ' ')) { //split the string by spaces and store into token[0], token[1], etc.
            i++;
        }
        //token[0] stores the day of week
        //token[1] stores the time (i.e "14:32")
        //token[2] stores duration

        istringstream s2(token[1]);
        string time_values[2];
        i = 0;

        while(getline(s2, time_values[i], ':')) { //split token[1] by ':'
            i++;
        }
        //time_values[0] stores hour
        //time_values[1] stores minute

        //rename variables for readibility
        string day = token[0];
        int hr = atoi(time_values[0].c_str()); //atoi to convert string to integer

        int minute = atoi(time_values[1].c_str());
        int duration = atoi(token[2].c_str());
        double cost=0; //accumulator
        int start_time = (hr*60)+minute;
        int end_time = start_time+duration;
        int startzone, endzone;

        if (day == "Mo" || day == "Tu" || day == "We" || day == "Th")
            {
                day == "weekday";
            }
            if (day == "Sa" || day == "Su")
            {
                day == "weekend";
            }
    //assigning each starting time to a zone
            if ((day == "weekday" || day == "Fr") && (start_time >= 480 && start_time < 1080))
            {
                startzone = 1; //call starts on hours
            }
            if ((day == "weekday" || day == "Fr") && (start_time <= 480))
            {
                startzone = 2; //call starts before 8 am
            }
            if ((day == "weekday" || day == "Fr") && (start_time >= 1080))
            {
                startzone = 3; //call starts after 6 pm
            }
            if (day == "weekend")
            {
                startzone = 4; //call starts on the weekend
            }
    //assigning each ending time to a zone
    //this program will handle at most 3 zone changes in one call.

            if (day == "weekday" && (end_time >= 480 && end_time <= 1080))
            {
                endzone = 1; //call ends on-hours the same day
            }
            if (day == "weekday" && (end_time >= 1080 && end_time <= 1920))
            {
                endzone = 2; //call ends after 6 pm on the same day, before 8 am on the next day
            }
            if (day == "weekday" && (end_time > 1920 && end_time <= 2520))
            {
                endzone = 3; //call ends on-hours on the next day
            }
            if (day == "weekday" && (end_time > 2520))
            {
                endzone = 4; //call ends after 6 pm the next day
            }
            if (day == "weekend" && (end_time <= 2880))
            {
                endzone = 5; //call starts and ends on the weekend
            }
            if (day == "Fr" && (end_time >= 1440 && end_time <= 2880))
            {
                endzone = 6; //call goes from weekday to weekend
            }
            if (day == "Su" && (end_time >= 1440 && end_time <= 1920))
            {
                endzone = 7; //call goes from weekend to weekday off-hours
            }

        //Cost calculations
        //CALL STARTS ON HOURS
                if (startzone == 1 && endzone == 1) //call is entirely within on-hours
                {
                    cost = duration*0.4;
                }
                if (startzone == 1 && endzone == 2) //call starts on-hours and ends before 8 am the next day
                {
                    cost = ((1080-start_time)*0.4) + ((end_time-1080)*0.25);
                }
                if (startzone == 1 && endzone == 3) //call starts on-hours and ends on-hours the next day
                {
                    cost = ((1080-start_time)*0.4) + (840*0.25) + ((end_time-1920)*0.4);
                }
                if (startzone == 1 && endzone == 4) //call starts on-hours and ends after 6 pm the next day
                {
                    cost = ((1080-start_time)*0.4) + (840*0.25) + (600*0.4) + ((end_time-2520)*0.25);
                }
                if ((startzone == 1 && endzone == 6)) //call starts on hours friday and ends on the weekend
                {
                    cost = ((1080-start_time)*0.4) + ((360)*0.25) + ((end_time-1440)*0.15);
                }

        //CALL STARTS OFF HOURS
                if (startzone == 2 && endzone == 2) //call starts before 8 am and ends before 8 AM the next day
                {
                    cost = ((480-start_time)*0.25) + (600*0.4) + ((end_time-1440)*0.25);
                }
                if (startzone == 2 && endzone == 3) //call starts before 8 am and ends on-hours the next day
                {
                    cost = ((480-start_time)*0.25) + ((end_time-1920)*0.25);
                }
                if (startzone == 2 && endzone == 6) //call starts before 8 AM friday and ends on the weekend
                {
                    cost = ((480 - start_time)*0.25) + (600*0.4) + (360*0.25) + ((end_time-1440)*0.15);
                }
                if (startzone == 3 && endzone ==6) //call starts after 6 PM friday and ends on the weekend
                {
                    cost = ((1440-start_time)*0.25) + ((end_time-1440)*0.15);
                }
                if ((startzone == 3 && endzone == 2) || (startzone == 2 && end_time <= 480)) //call is entirely within off-hours
                {
                    cost = duration*0.25;
                }
                if ((startzone == 3 && endzone == 3)) //call starts after 6 pm and ends on-hours the next day
                {
                    cost = ((1920-start_time)*0.25) + ((end_time-1920)*0.4);
                }
                if ((startzone == 3 && endzone == 4)) //call starts after 6 pm and ends after 6 pm the next day
                {
                    cost = ((1920-start_time)*0.25) + (600*0.4) + ((end_time-2520)*0.25);
                }

        //CALL STARTS ON WEEKEND
                if (startzone == 4 && endzone == 5) //call is entirely within weekends
                {
                    cost = duration*0.15;
                }
                if (startzone == 4 && endzone == 7) //call starts on sunday and ends before 8 am monday
                {
                    cost = ((1440-start_time)*0.15) + ((end_time-1440)*0.25);
                }

        cout << setw(4)<< endl;
        cout << day << " " << hr << ":" << minute << " " << duration << " $" << cost << "\n";
        total += cost;

    }
    cout << setw(4) << endl;
    cout << "\tTotal $" << total << "\n";

}
#包括
#包括
#包括
#包括
#包括
#包括
使用名称空间std;
ifstream fin(“call_history.txt”)//从文件中读取
//int main
int main(){
字符串温度;
双倍合计=0.0;
while(getline(财务、温度)){
IstringStreams(温度);
字符串标记[3];
int i=0;
while(getline(s,token[i],“”)){//将字符串按空格分割并存储到token[0],token[1]等中。
i++;
}
//令牌[0]存储星期几
//令牌[1]存储时间(即“14:32”)
//令牌[2]存储持续时间
istringstream s2(令牌[1]);
字符串时间_值[2];
i=0;
while(getline(s2,time_值[i],':'){//split token[1]by':'
i++;
}
//时间\u值[0]存储小时数
//时间_值[1]存储分钟
//为可读性重命名变量
字符串日期=令牌[0];
int hr=atoi(time_值[0].c_str());//将字符串转换为整数的atoi
int minute=atoi(时间值[1].c_str());
int duration=atoi(令牌[2].c_str());
双重成本=0;//累加器
int开始时间=(小时*60)+分钟;
int end_time=开始时间+持续时间;
int startzone,endzone;
如果(day==“Mo”| day==“Tu”| day==“We”| day==“Th”)
{
day==“工作日”;
}
如果(日==“Sa”|日==“Su”)
{
日==“周末”;
}
//将每个开始时间指定给区域
如果((日=“工作日”| |日==“Fr”)和&(开始时间>=480和开始时间<1080))
{
startzone=1;//通话开始时间为小时
}
如果((日==“工作日”|日==“Fr”)&&(开始时间=1080))
{
startzone=3;//下午6点后开始通话
}
如果(日=“周末”)
{
startzone=4;//周末开始通话
}
//将每个结束时间指定给区域
//此程序在一次调用中最多可处理3个区域更改。
如果(日期==“工作日”&&(结束时间>=480&&结束时间=1080&&结束时间1920&&结束时间2520))
{
endzone=4;//第二天下午6点后通话结束
}
如果(day==“weekend”&&(end_time=1440&&end_time=1440&&end_time=1440&&end_time问题不完全在于公式,而在于浮点数的固有限制

这里的关键问题是,在任何两个数字之间,都有无穷多个实数(事实上,实数的数量是不可数的无穷多个),并且在一个双精度中只有有限的空间来表示它们。因此,将存在舍入误差

此外,由于它们存储在基数2中,而不是基数10中,因此会存在一些数字,它们看起来确实应该是可精确表示的,但实际上不是。标准示例是
0.1
;在基数2中没有有限表示

考虑以下几点:

#include <cstdio>
int main() {
    double x = 0.0;
    for (int i = 0; i < 10; i++) {
        x += 0.1;
        printf("%.20f\n", x);
    }
}
0.10000000000000000555
0.20000000000000001110
0.30000000000000004441
0.40000000000000002220
0.50000000000000000000
0.59999999999999997780
0.69999999999999995559
0.79999999999999993339
0.89999999999999991118
0.99999999999999988898
现在,最后一个数字应该是1.0,这是完全可以表示的,但是到那时,舍入误差已经加起来了,所以我们得到了一些稍微不同的结果。这就是代码中发生的情况。有一些微小的舍入误差加起来达到6.9531e-308,如果没有舍入的话,这个值应该是0。最简单的解决方案是它只是以一种格式打印,强制它将最终答案四舍五入到一个精确的点。例如,如果我们将
printf(“%.20f\n”)
更改为
printf(“%.1f\n”)
在上面的示例中,它将准确地打印出您期望的数字。在您的示例中,仅强制它不使用科学记数法就足以使其四舍五入为0

double x = 6.9531e-308;
printf("%e\n", x);
printf("%f\n", x);
std::cout << x << "\n";
std::cout << std::fixed << x << "\n";
如果您想了解浮点数如何工作的具体细节(我建议您最终也要了解,即使您还没有处于教育阶段),本文是标准参考:

附录:


此外,您还可以使用
day==“weekday”
您的意思是
day=“weekday”
在一些地方,这就是为什么它接近于0。这可能是一个更重要的问题,尽管这不是一个有趣的问题。

1.我不希望成本显示为0,我希望它显示为调用的成本,通过适当的公式2计算。我如何确定一个值?是否有可能所有if语句都不存在der cost calculation从未被调用,因此
cost
始终为
0
,这意味着
total
始终为
0
?是否尝试调试代码?调试器。使用调试器。调试器将帮助您在查看变量中的值时分别执行每条语句。请使用调试器的结果编辑您的帖子请编辑问题,添加输入示例,即预期计算(如何计算成本)而你的程序给你的输出呢?你发布的代码是输出零还是一个非常小的正数?你需要一次只关注一个问题,而不是不同版本的代码会做什么。还有,是的,调试器。谢谢
6.953100e-308
0.000000
6.9531e-308
0.000000