1

让我进一步解释一下。我正在编写一个代码来计算游泳池在以填充率填充一段时间后的水量。采用的输入是length,以英尺为单位,以秒为单位填充水池width的时间美制加仑/分钟为单位的水池中的注水率,以美制加仑为单位的水池中已经存在的水量。根据这些信息,我通过将长度、宽度和深度相乘并将其转换为美制加仑来计算总池水容量。depthtimeToFillPoolfillingRatepoolCurrWaterAmounttotalPoolCapacity

我问用户池中已有多少水,然后计算并向用户显示适当的消息,例如如果池已满或在给定时间内注满的水将超过池容量,是否可以注满水?

我假设输入的所有值都是正数或等于零(如果允许为零)。

#include <iostream>
#include <iomanip>
#include <cmath>  //for fabs() functions

using namespace std ;

int main()
{
    double timeToFillPool ;
    double length, width, depth, fillingRate ;
    double poolCurrWaterAmount, totalPoolCapacity ;
    const double CUBIC_FOOT_TO_USGALLON = 7.48052 ; //i.e. 1 cubic foot = 7.48052 US Gallon
    //setting tolerance value for comparing floating point numbers to 1/10000
    //any thing less will be considered zero
    const double EPSILON = 0.0001 ;

    //preparing the output stream to print floating numbers in decimal
    //form with precision to print two digits after decimal point
    cout << fixed << setprecision(2);

    cout << "Please enter swimming pool's dimensions,capacity,fill rate & drain rate information.\n";
    cout << "Enter Length in foot                         : " ;
    cin >> length ;

    cout << "Enter width in foot                          : " ;
    cin >> width ;

    cout << "Enter depth in foot                          : " ;
    cin >> depth ;

    cout << "Enter filling rate of water in US Gallon/min : " ;
    cin >> fillingRate ;

    //calculating totalPoolCapacity in US Gallon
    totalPoolCapacity = length * width * depth * CUBIC_FOOT_TO_USGALLON ;
    cout << "\n\nTotal pool capacity                          = " << totalPoolCapacity << " US Gallon." ;

    cout << "\n\nPlease enter current amount of water in pool in US Gallon to " ;
    cout << "\nfill the pool according to filling rate for the specific amount of time in minutes : " ;
    cin >> poolCurrWaterAmount ;
    //to check minimum and maximum range of current amount of water.
    while( !(poolCurrWaterAmount >= 0.0   &&   poolCurrWaterAmount <= totalPoolCapacity ) )
    {
        cout << "\nYou have entered in-valid value for current amount of water!"
             << "\nEnter current amount of water value from 0 to maximum capacity of pool "
             << setw(10) << totalPoolCapacity << " in US Gallon : " ;
        cin >> poolCurrWaterAmount ;
    }

    cout << "\nPlease enter time in minute to fill water in pool : " ;
    cin >> timeToFillPool ;


    //Calculations and message displayed are on the basis of whether the filling water
    //will cause overflow of water after filling the pool or not.
    //managing floating point eqaulity  poolCurrWaterAmount == totalPoolCapacity
    //setting the tolerance value EPSILON to 1/10000 = 0.0001 of a US Gallon
    if ( fabs(poolCurrWaterAmount - totalPoolCapacity) < EPSILON)
    {
        cout << "\n\nPool is Full. Water cannot be added." ;
        cout << "\nTotal water in pool is " << setw(10) << totalPoolCapacity << " US Gallon." ;
    }
    else if (fillingRate * timeToFillPool > (totalPoolCapacity - poolCurrWaterAmount) )
    {
        //case to check that time entered for filling water will cause overflow of water or not
        cout << "\n\nWarning! Pool will be overflowed with water! No water added!" ;
        cout << "\nCurrent amount of water in pool = "
             << setw(10) << poolCurrWaterAmount << " US Gallon." ;
        cout << "\nMaximum time required to completely fill the pool at\nfilling rate of "
             << setw(10) << fillingRate << " US Gallon/min is "
             << setw(10) << ( (totalPoolCapacity - poolCurrWaterAmount) / fillingRate ) << " minute." ;
    }
    else   //case where time entered for filling water will not cause overflow of water in pool
    {
        cout << "\n\nCurrent amount of water in pool = "
             << setw(10) << poolCurrWaterAmount << " US Gallon." ;
        cout << "\nAfter filling "
             << setw(10) << (fillingRate * timeToFillPool) << " US Gallon at filling rate of "
             << setw(10) << fillingRate << " US Gallons/min for "
             << setw(10) << timeToFillPool << " minute\nthe new amount of water in pool is "
             << setw(10) << ( poolCurrWaterAmount + fillingRate * timeToFillPool ) << " US Gallon." ;
    }

}
//end of main function
this is the ouput of the program: -
***********************************

Please enter swimming pool's dimensions,capacity,fill rate & drain rate information.
Enter Length in foot                         : 3
Enter width in foot                          : 2
Enter depth in foot                          : 2
Enter filling rate of water in US Gallon/min : 4


Total pool capacity                          = 89.77 US Gallon.

Please enter current amount of water in pool in US Gallon to
fill the pool according to filling rate for the specific amount of time in minutes : 89.77

You have entered in-valid value for current amount of water!
Enter current amount of water value from 0 to maximum capacity of pool      89.77 in US Gallon :

************************************************************************************************

问题是存储的内部值totalPoolCapacity是 89.76624 并且由于setprecision(2)它将值四舍五入到 89.77 所以当我输入 89.77 它不接受它作为正确的值,尽管根据显示消息它应该是正确的值。我不想向用户展示全部价值。

还请解释如何处理这个计算setprecision(2) (totalPoolCapacity - poolCurrWaterAmount) / fillingRate

EPSILON以及比较浮点数有什么好处。

因此,计算并显示给用户的时间不会影响具有舍入效果的整体计算。这就是用户所看到的,程序通过操纵浮点数的内部表示及其四舍五入效果来根据该行为行事。

4

3 回答 3

2

您永远不应该进行浮点比较,例如poolCurrWaterAmount <= totalPoolCapacity.

相反,您应该这样做(poolCurrWaterAmount - totalPoolCapacity) < epsilon

在您的情况下,epsilon 应该是 0.005。

通常,对于相等运算符,epsilon 可以像 DBL_EPSILON一样小。

要深入了解该主题,包括更严格的算法,请参阅compare-floating-point-numbers-2012-edition

于 2019-11-17T20:51:48.030 回答
1

您可以做的一件事是调用std::fesetround(FE_DOWNWARD);,以便您显示的数字向下舍入而不是向上舍入。这样一来,当用户重新输入他在输出中看到的舍入值时,输入的值会略小于池的实际容量,而不是略多,因此可以避免触发您的错误消息。

或者,如果您不喜欢这种方法,您也可以只设置poolCurrWaterAmount = std::min(poolCurrWaterAmount, totalPoolCapacity);而不是发出错误消息,这样如果用户输入的值大于池的容量,则将其视为输入的值等于池的容量容量。

于 2019-11-17T20:37:48.273 回答
1

对于第一个问题:

问题是存储在 totalPoolCapacity 中的内部值是 89.76624 并且由于 setprecision(2) 它将值四舍五入到 89.77 所以当我输入 89.77 它不接受它作为正确的值虽然它应该是正确的值根据显示信息。我不想向用户展示全部价值。

如果用户输入的值等于 的舍入值,您可以尝试将 设置poolCurrentWaterAmount为,例如:totalPoolCapacitytotalPoolCapacity

#include <iostream>
#include <iomanip>
#include <sstream>

double round_double_value(double val, int prec) {
    std::stringstream strstream;
    strstream << std::fixed << std::setprecision(prec) << val;
    double result;
    strstream >> result;
    return result;
}

int main()
{
    const double CUBIC_FOOT_TO_USGALLON = 7.48052 ;
    const double EPSILON = 0.0001 ;

    double length = 3.0;
    double width = 2.0;
    double depth = 2.0;
    double fillingRate = 4.0;

    double totalPoolCapacity = length * width * depth * CUBIC_FOOT_TO_USGALLON ;
    int out_precision = 2;
    std::cout << std::fixed << std::setprecision(out_precision);
    std::cout << "Total pool capacity = " << totalPoolCapacity << " US Gallon.\n" ;

    double poolCurrWaterAmount = 89.77;
    std::cout << "You entered current pool water amount = " << poolCurrWaterAmount << '\n';

    if ((poolCurrWaterAmount > totalPoolCapacity)
        && (poolCurrWaterAmount == round_double_value(totalPoolCapacity, out_precision)) ) {
        // Assume the user meant to input the maximum..
        poolCurrWaterAmount = totalPoolCapacity;
    }

    if( !(poolCurrWaterAmount >= 0.0
            &&  poolCurrWaterAmount <= totalPoolCapacity ) )
    {
        std::cout << "You have entered in-valid value for current amount of water!\n";
        return(1);
    }

    return 0;
}
于 2019-11-17T23:46:36.183 回答