C 打印浮点值和int值以进行简单计算(值不相加)

C 打印浮点值和int值以进行简单计算(值不相加),c,floating-point,C,Floating Point,对于设计用于将美元值输入转换为其可能组成部分的程序,浮点/整数计算有困难。例如,如果输入$1234.56,程序将输出“1$1000钞票、2$100钞票、1$20钞票、1$10钞票、4$4钞票、2个25美分、1镍币和1美分” 最大的问题是如何计算便士。如果用户输入0.03美元,输出将有所不同(有时我得到3美分;其他时候我得到2美分)。我想我现在已经解决了这个问题,但我想了解我为什么要解决这个问题,更重要的是,我想解决根本问题:在计算流的某个地方,编译器似乎“剃掉”了值(例如,.01变为.00999

对于设计用于将美元值输入转换为其可能组成部分的程序,浮点/整数计算有困难。例如,如果输入$1234.56,程序将输出“1$1000钞票、2$100钞票、1$20钞票、1$10钞票、4$4钞票、2个25美分、1镍币和1美分”

最大的问题是如何计算便士。如果用户输入0.03美元,输出将有所不同(有时我得到3美分;其他时候我得到2美分)。我想我现在已经解决了这个问题,但我想了解我为什么要解决这个问题,更重要的是,我想解决根本问题:在计算流的某个地方,编译器似乎“剃掉”了值(例如,.01变为.009999)。是因为我在对同一个变量,即“amount”执行递归计算吗?有没有更干净的方法来做我在这里要做的事情?(我仅限于switch/if选择语句,不使用函数,也不使用数组。)

链接到完整代码

#包括
int main(){
浮动金额,票据四分之一,票据一角,票据五分之一,票据一便士;
一角硬币、一角硬币、五分硬币、一便士硬币;
printf(“Ex 5.15:将十进制美元转换为硬币”);
printf(“===============================================================================\n\n”);
printf(“输入您的金额(例如98):$”;
scanf(“%f”和金额);
/************************************/
/*大于最大值的计算*/
/************************************/
如果(金额>=1)
printf(“\n您的钱太多!\n\n”);
/************************************/
/*硬币的计算*/
/************************************/
否则如果(金额<1&&金额>0){
账单季度=金额/.25;
账单季度=金额/.25;
金额=((账单季度-账单季度)*.25);
(账单季度>=1和账单季度<4)?(printf(“您有%d个季度,账单季度”):(printf(“”);
账单=金额/.10;
账单金额=金额/.10;
金额=(账单金额-账单金额)*.10;
(bill_dime>=1和bill_dime=1和bill_nickel<2)?(printf(“您有%d镍”,bill_nickel)):(printf(“”);
账单=金额/.01;
账单_penny_f=金额/.01;
金额=(比尔便士比尔01;
(bill_penny_f>0和&bill_penny_f<5)?(printf(“您有%.0f pennies\n”,bill_penny_f)):(printf(“”);
}
否则,如果(金额==0)
printf(“您没有钱!\n”);
其他的
printf(“您负债!\n”);
返回0;
}

将二进制浮点用于金融代码有各种缺陷。OP的代码展示了其中的一些。在不涉及其他表示金钱的方式(各有优缺点)的情况下,这个答案提供了一些方法,可以提高
对金钱的双重使用,因为它适用于OP的代码

  • 货币的不精确表示
  • 回想一下,
    double
    通常可以准确地表示大约264个不同的数字<代码>0.10
    不是其中之一。所以下面的商通常会导致一个非整数

    float amount;
    ...
    amount / .10;
    
    将商赋给
    int
    会导致截断值。如果
    为1.9999…,
    bill_dime
    的值为1

    int bill_dime;
    ...
    bill_dime = amount / .10;
    
  • 无法控制不是0.01的精确倍数的输入
  • 如何处理用户输入,如
    “0.125”
    -->
    金额=0.125

    0.125
    可以精确地表示为
    double
    ,因此输入时没有舍入问题。然而,代码并没有说明如何舍入这样一个值,或者如何处理分数0.01

  • 无法控制输入舍入值
  • 如何处理无法准确表示值的用户输入,如
    “0.10”
    -->呢?因此,附近的
    数量=0.10f
    结果

    具有接近0.01的
    浮点值
    0.01f,可能与
    双精度
    0.01不同。此差异可能导致
    amount/.10产生意外结果。混合
    double
    float
    导致了此问题


    对于采用FP的财务代码,不要使用
    float
    ——问题太多

    对于OP的学员使用FP和财务代码,建议将FP输入转换为整数进行更改计算。由于下面的转换为
    long
    肯定不会溢出,因此可以将此问题放在一边

    printf("Enter your amount (e.g .98): $ ");
    double amount;
    if (scanf("%lf", &amount) != 1) Handle_NonNumericInput();
    
    if (amount >= 1.0 || amount < 0.0)
      printf("\nYou have too much/too little money!\n\n");
    

    对货币类型使用定点算法;浮点是完全不合适的(尤其是二进制浮点)。@TobySpeight货币类型的定点算法也有弱点。“浮点是完全不合适的”-->十进制FP很好——除了它缺乏支持之外。这是一种折衷,不管走哪条路。@chux,我从来没有尝试过用十进制浮点数来赚钱;我宁愿将这些指数数字用于实际值,而不是用于缩放(因此在意外时间改变(绝对)精度)。但是如果你有这样的经验,我很想听听它是如何为你工作的,也许在某个地方有一个答案?@OP“是因为我在执行一个…[这个]还是[那个]?”-->要点是,当使用FP来赚钱时,代码需要一个如何处理结果的定义,这个结果只能接近最小单位0.01的倍数。@chux感谢你的回答。我的帖子有什么不完整的地方?我是一个初学者,并不是说我想依靠它,而是我对我的文章不完整感到困惑。最后,作者(KN King)到目前为止介绍的唯一变量类型是float和int;所以,我想知道这个练习是否是为了迫使读者避免使用float。
    printf("Enter your amount (e.g .98): $ ");
    double amount;
    if (scanf("%lf", &amount) != 1) Handle_NonNumericInput();
    
    if (amount >= 1.0 || amount < 0.0)
      printf("\nYou have too much/too little money!\n\n");
    
     else {
       // round ... to the nearest integer value, rounding halfway cases away from zero,
       long cents = lround(amount * 100.0);
       // 0 <= cents <= 100
       // Need to decide how to handle cents == 0 or cents == 100 here.
    
       bill_quarter = cents / 25;
       cents %= 25;
    
       if (bill_quarter) {
         printf("You have %d quarters\n", bill_quarter);
       }
    
      bill_dime = cents / 10;
      cents %= cents % 10;
    
       if (bill_dime) {
         printf("You have %d dimes\n", bill_dime);
       }
    
    // "You have %d nickel"
    "You have %d nickels"