When testing the program the result was obtained:
Input - value
9.995 - 9.99 (instead of 10.00)
0.995 - 1.00
152.995 - 153.0
7.895 - 7.89 (instead of 7.90)
The following is the source code of the program:

1st file

int main() { setlocale(LC_ALL, "Russian"); double n,rub,cop; cout << "Преобразование числа в денежный формат." << "\n"; cout << "Введите дробное число - "; cin >> n; cop = modf(n, &rub); cop = roadcent(cop); if (cop == 100) { cop = 0; ++rub; } cout << n << "руб. - это " << rub << " руб. " << cop << " коп." << "\n"; system("pause"); return 0; } 

2nd file

 double roadcent(double k) { k *= 100; int l = (int)(k * 10) % 10; if (l == 5) { return floor(k + 1); } else { return floor(k + 0.5); } } 

What is the result of the result? What are the options for correcting this error?

    2 answers 2

    The problem, of course, is that you use a floating point numeric data type. As is well known, in this type only those fractional values ​​whose denominator is equal to a power of two can be accurately represented. For your number 9.995 real value is 9.9949999999999992184029906638897955417633056640625 , which is the closest to your number, which can be expressed in the double data type. You get l == 4 .

    Here's a small C # program (based on John Skit’s code ) that shows what's going on under the hood of double : http://ideone.com/hTiobV#stdout .


    What to do? For example, you can enter numbers as strings, manually find the part of the number to the decimal point and the part after, and round off manually.

    Some languages ​​have a ready-made data type that works with such numbers (for example, decimal from C # or java.math.BigDecimal from Java), a stronger <boost/multiprecision> may be suitable for C ++ (but you have to connect boost).

    If it is necessary to count pennies and rubles, then the correct idea is NOT to use floating point numbers, but to emulate fixed-point numbers through integers. Those. count for a penny. If there are not enough digits, try long long int. If long long is not enough, then it is time to implement the arithmetic of bignum. Students usually implement it on top of single-byte integer arrays (this is inefficient from memory, but informative).

    • The problem is in the input, input something with a decimal point. - VladD
    • @VladD to enter a string and convert it into an integer (taking into account a possible point inside) is a small problem. - andy.37 pm
    • @ andy.37: The fact of the matter is that the problem of the vehicle is precisely the loss of accuracy when entering, as it seems to me. - VladD
    • I agree with @ andy.37 - if you turn on the brain, then the line is not a problem to make out. Even if you do it by the hand - gecube