В этом коде есть ошибка
Я - решатель проблем начального уровня в этом онлайн-судье. Я неплохо справился с первыми 20 задачами. Но нет. 21 Я застрял. Я написал этот код:
#include <stdio.h>
#include <math.h>
int main()
{
double notes[] = {100, 50, 20, 10, 5, 2};
double moedas[] = {1, 0.50, 0.25, 0.10, 0.05, 0.01};
int amount_of_notes[6];
int amount_of_moedas[6];
double n, x;
int i, j;
scanf("%lf", &n);
printf("NOTAS: \n");
for(i = 0; i < 6; i++)
{
x = fmod(n, notes[i]);
amount_of_notes[i] = n/notes[i];
n = x;
printf("%d nota(s) de R$ %.2lf\n", amount_of_notes[i], notes[i]);
}
printf("MOEDAS: \n");
for(j = 0; j < 6; j++)
{
amount_of_moedas[j] = n/moedas[j];
x = fmod(n, moedas[j]);
n = x;
printf("%d moeda(s) de R$ %.2lf\n", amount_of_moedas[j], moedas[j]);
}
return 0;
}
Этот код находится в C. Этот код преобразует число в некоторые банкноты и монеты. Но когда я ввожу 54.54
вывод приходит так:
NOTAS:
0 nota(s) de R$ 100.00
1 nota(s) de R$ 50.00
0 nota(s) de R$ 20.00
0 nota(s) de R$ 10.00
0 nota(s) de R$ 5.00
2 nota(s) de R$ 2.00
MOEDAS:
0 moeda(s) de R$ 1.00
1 moeda(s) de R$ 0.50
0 moeda(s) de R$ 0.25
0 moeda(s) de R$ 0.10
0 moeda(s) de R$ 0.05
3 moeda(s) de R$ 0.01
как вы можете видеть, что только в последней строке 3
показывает, где он должен показывать 4
, Я так старался найти ошибку в коде. Я провалил. Пожалуйста, помогите найти ошибку этого кода!
2 ответа
Избегайте переменных с плавающей точкой для всего, что требует точности. Поплавки не точны, и вы столкнетесь с ошибками округления. В вашем случае вы ожидаете 4, но получаете 3 из-за ошибок округления.
Вместо этого делайте все вычисления, используя целые числа, и используйте центы в качестве базовой единицы.
Что-то вроде:
#include <stdio.h>
#include <math.h>
int main()
{
int notes[] = {10000, 5000, 2000, 1000, 500, 200}; // Unit is cents
int moedas[] = {100, 50, 25, 10, 5, 1}; // Unit is cents
int amount_of_notes[6];
int amount_of_moedas[6];
double n;
int x;
int n_int;
int i, j;
scanf("%lf", &n);
n_int = 100 * n; // Unit is cents
printf("NOTAS: \n");
for(i = 0; i < 6; i++)
{
x = n_int / notes[i];
amount_of_notes[i] = x;
n_int -= x * notes[i];
printf("%d nota(s) de R$ %.2lf\n", amount_of_notes[i], notes[i]/100.0);
}
printf("MOEDAS: \n");
for(j = 0; j < 6; j++)
{
x = n_int / moedas[j];
amount_of_moedas[j] = x;
n_int -= x * moedas[j];
printf("%d moeda(s) de R$ %.2lf\n", amount_of_moedas[j], moedas[j]/100.0);
}
return 0;
}
Входные данные:
54.54
Выход:
NOTAS:
0 nota(s) de R$ 100.00
1 nota(s) de R$ 50.00
0 nota(s) de R$ 20.00
0 nota(s) de R$ 10.00
0 nota(s) de R$ 5.00
2 nota(s) de R$ 2.00
MOEDAS:
0 moeda(s) de R$ 1.00
1 moeda(s) de R$ 0.50
0 moeda(s) de R$ 0.25
0 moeda(s) de R$ 0.10
0 moeda(s) de R$ 0.05
4 moeda(s) de R$ 0.01
Ошибка связана с тем, как компьютеры обрабатывают числа с плавающей запятой. Этот ресурс имеет хорошее объяснение по теме.
Есть несколько способов решения этой проблемы, в вашем случае я считаю использование целых чисел лучшим вариантом. Вы можете начать со своих значений "notes" и "moedas" в виде целых чисел (умножив их все на 100) и сделать то же самое с вводом. Это не изменит конечный результат, но вы будете иметь дело с целыми числами вместо чисел с плавающей запятой. И так как целые числа точны (без ошибок округления), результат будет тем, что вы ожидаете.
Здесь есть подтверждение концепции на основе вашего кода. Обратите внимание, что я внес только минимальные изменения, которые могли бы заставить его работать, есть много возможностей для улучшения.