Работа с числами и числами - PullRequest
3 голосов
/ 17 января 2012

Я создал программу, похожую на банкомат, которая хранит деньги на счету человека. Когда человек снимает деньги со счета, он вычитает их со счета вместе с доплатой в размере .50. У меня проблема в работе с целыми числами и числами с плавающей запятой. Я преобразовал целочисленную учетную запись в число с плавающей запятой, но при попытке распечатать инструкцию выдает сообщение об ошибке. Может кто-нибудь сказать мне, что я делаю не так?

#include <stdio.h>

int main (void) {
    int account = 2000;
    int withdrawal;
    float charge = 0.50;

    printf ("How much money would you like to take out? ");
    scanf ("%i", &withdrawal);

    while (withdrawal % 5 != 0) {
        printf ("Withdrawal must be divisible by 5. ");
        scanf("%i", &withdrawal);
    }

    account = ((float) account - charge) - withdrawal;

    printf("Remaining account: %.2f\n", account);

    return 0;
}

Ответы [ 7 ]

7 голосов
/ 17 января 2012
int account = 2000;
printf("Remaining account: %.2f\n", account);

Это неправильно; это должно быть "%d" для целого числа, или лучше, измените тип переменной account на что-то, что может представлять собой 0,50, который вы набираете. Я не рекомендую вам использовать (неточные) float s за деньги. Вы не хотите снимать 10.499999997, когда имели в виду 10.5. Вам нужно подумать о правилах точности и округления, которые вы бы использовали. AFAIK они оба предписаны законами или что-то.

5 голосов
/ 17 января 2012

Вы просто не можете использовать значения с плавающей запятой для представления валюты, поскольку они имеют неправильные свойства.Не все числа являются точно представимыми, поэтому у вас будут «таинственные» эффекты.

Лучше использовать подход с фиксированной запятой, самый простой - взять большой целочисленный тип, такой как long, а затемпросто умножьте его на целое число, обычно 100, если все, что вам нужно, это целые центы (для валюты США).Если вам нужны доли центов, умножьте их еще на 10 000, чтобы иметь возможность представить все значения вплоть до 1/100: тысячный цент.

При этой схеме $ 1 будет:

long one_dollar = 1 * 10000;

И 13 центов будут:

long thirteen_cents = 13 * 100;

Обратите внимание, что это, в свою очередь, ограничивает сумму денег, которую вы можете представлять.В конце концов, вы можете обнаружить, что вам нужна библиотека произвольной точности, чтобы получить "неограниченные" целочисленные прецизионные значения.

3 голосов
/ 17 января 2012

Пожалуйста, , не используйте поплавки при обработке денег. Используйте целочисленный тип as для отслеживания центов, а затем конвертируйте его при выводе в доллары и центы (или любую другую валюту).

В частности, 0,1 десятичное не имеет точного представления с плавающей запятой. Вместо этого он представлен в виде бесконечной повторяющейся двоичной дроби (0,19999999999 .... hex ). Аналогично, 0,01 десятичное число приблизительно равно 0,028F5C28F ... hex .

1 голос
/ 17 января 2012

Предупреждение, которое вы видите, связано с тем, что вы передаете int в printf(), передав ему %.2f в качестве строки формата.Эта строка формата должна использоваться для чисел с плавающей запятой.См. printf .

Однако в коде есть более существенный недостаток.Не следует использовать переменные с плавающей запятой для представления чисел, когда требуются точные десятичные дроби, особенно при работе с денежными суммами.Короче говоря, причина не использовать числа с плавающей запятой в вашем приложении состоит в том, что десятичные дроби не могут быть представлены точно.В каждой позиционной системе счисления некоторые числа представлены бесконечной повторяющейся последовательностью.Например,

в десятичной системе 1/3 представляется как 0,33 [3]

(квадратные скобки, обозначающие бесконечно повторяющуюся последовательность цифр).Аналогично, в двоичном коде некоторые числа требуют представления бесконечной последовательности нулей и единиц.Например,

в двоичной системе, 1/10 - это 0,000110011. [101]

Поскольку регистры и ячейки памяти имеют конечную длину, они округляются в большую или меньшую сторону и представляютчисло немного выше или ниже 0,1.Таким образом, вы не можете сохранить точное значение 0,1 в float или double.

. Подробнее см. Что должен знать каждый учёный-информатор об арифметике с плавающей точкой .

Например, можно использовать целочисленные переменные, представляющие центы.

1 голос
/ 17 января 2012

Сделайте свою жизнь немного проще, и вместо того, чтобы думать о своих «целых» как о долларах, думайте о них как о «центах», тогда вам не понадобятся числа с плавающей запятой.

0 голосов
/ 17 января 2012

При работе с деньгами вам, вероятно, следует использовать двоичные десятичные дроби. Это позволит вам использовать одну переменную для долларов и центов. Пока вы это делаете, вы можете указать структурное объединение typedef, которое позволит вам указывать значение только в долларах, центах, целых долларах и только в центах. Если не считать обмена с другими валютами, это будет хорошо практически для каждого денежного сценария.

0 голосов
/ 17 января 2012

вы распечатываете учетную запись, как если бы это было число с плавающей запятой (%2f), даже если это целое число, вместо него следует использовать спецификатор формата %d

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...