-2

I want to convert a floating point number like 0.15 -> 15 or 0.4 -> 4

My idea is to

  1. Multiply a number with amount of floating point places.

  2. Floor it.

  3. Cast it to (int).

Can't figure how to do the first step.

Clarification: I have to make a program that uses a greedy algorithm, User enters change_owed. This program would then check for the lowest number of coins possible to give-out.

Code:

#include <ctype.h>
#include <stdio.h>
int main(void)
{
    int coins = 0;
    float cash_owed = 0;
    
    do
    {
        printf("Cash owed: ");
        scanf("%f" , &cash_owed);
    }
    while(cash_owed < 0);
    
    while(cash_owed > 0)
    {
        if(cash_owed >= 0.25)
        {
            cash_owed -= 0.25;
            printf("Cash owed: %f\n", cash_owed);
            coins++;
            printf("Coins: %d\n", coins);
        }
        else if(cash_owed >= 0.10)
        {
            cash_owed -= 0.10;
            printf("Cash owed: %f\n", cash_owed);
            coins++;
            printf("Coins: %d\n", coins);
        }
        else if(cash_owed >= 0.05)
        {
            cash_owed -= 0.05;
            printf("Cash owed: %f\n", cash_owed);
            coins++;
            printf("Coins: %d\n", coins);
        }
        else
        {
            cash_owed -= 0.01;
            printf("Cash owed: %f\n", cash_owed);
            coins++;
            printf("Coins: %d\n", coins);
        }
    }
    printf("%d\n", coins);
    return 0;
    }

Not my best design. But it fails on many different examples given below, Acc to my understanding it's due to floating-point arithmetic imprecision.

Fails for: 0.15, 1.6 and 4.2. wherein it skips one or more if statement due to floating-point arithmetic imprecision.

So I devised a new algo which will convert these values to proper int. Like

0.15 -> 15

So I have to work with integers to eliminate that float point errors, If this makes any sense

user14354509
  • 47
  • 1
  • 6
  • 4
    Well, if you want to go there, I wouldn't start from here ... ditch f-p and work in integer numbers of pennies/cents/whatever-you-call-them. Much easier to insert a `.` in the right place than to make f-p arithmetic behave as you want it to. – High Performance Mark Sep 28 '20 at 12:36
  • if performance is not imporant: **1)** convert it to string / char[], **2)** get rid of the decimal point and the left side of the decimal point, **3)** convert the reaminder into a numeric value again. done. – holex Sep 28 '20 at 12:38
  • 1
    You're going to run into serious problems with floating point inaccuracies. What if the user enters `0.34`, for example, and the closest floating point representation of that is `0.3399765`? Round it up? Then how would you handle the case where the user actually did enter `0.3399765`? You pretty much will have to know what the user entered just to be sure you handle it properly. You might as well just process the input string. – Andrew Henle Sep 28 '20 at 12:55
  • @holex _get rid of ... and the left side of the decimal point,_ I think the left side is still needed, is it not? – ryyker Sep 28 '20 at 12:58
  • To what precision are you interested in converting? i.e. is this mainly for currency conversion? Are we talking only about numbers with 2 decimal places such as `12.34`, or are you also trying to convert numbers such as `12.34545679`? – ryyker Sep 28 '20 at 13:02
  • 1
    If the user enters a number of dollars, then you do not want to convert .4 to 4; you want to convert .4 to 40, because .4 dollars is 40 cents. If you are getting the user’s input as a floating-point number and cannot change that, then simply multiply by 100 and round to the nearest integer using the `round` function: `int cents = round(x * 100);`. Then do the remaining work using cents. – Eric Postpischil Sep 28 '20 at 13:09
  • @ryyker, if it needed then keep it, that is not a question – but if they need the floating part as an integer, the left side needs to be get rid of first. – holex Sep 28 '20 at 13:17
  • @EricPostpischil - That is the question, isn't it? i.e. the bulk of content suggests currency, but then OP says _1) Multiply a number with amount of floating point places_, suggesting the fractional part is variable, up to how many decimal places has yet to be determined. – ryyker Sep 28 '20 at 13:17
  • @iLikeAss3 - Have you noticed that there are some questions in the comments that would be helpful if answered? Your question needs clarification before an accurate response can be offered. – ryyker Sep 28 '20 at 13:24
  • Do you post question about the same code under multiple accounts? Or do you copy code you do not understand? I saw the same type of code from about 4 accpounts in the lest few days. – 12431234123412341234123 Sep 28 '20 at 14:53
  • Please learn how most computers store a `float` and what values it can hold, what problems may occur and so on. Most implementations do not use decimal `float`s, in fact almost no implementations uses decimal `float`s. IEEE 754 is the most common. – 12431234123412341234123 Sep 28 '20 at 14:55

2 Answers2

0

to convert a floating point number like 0.15 -> 15 or 0.4 -> 4

  1. Recognize 0.15 and 0.4 are not exactly encodable as a floating point number as they are not dyadic as typically used: e.g. binary32. Instead a nearby value is saved in cash.

  2. Multiply the floating point number by 100. Since the product determination may round and the original number may only be close to a few digit decimal number, round the result. Using floor may take a value of xxx.9999... to xxx.0 rather than a more reasonable xxx.0 + 1.

    #include <math.h>
    long cash_in_cets = lround(cash * 100.0);
    

Proceed with rest of greedy algorithm using integer math and integer cents,


My crystal ball hints that the next version of C will specify decimal floating point numbers, which is a great solution for money.


Code can stay with only using FP types, yet test like (cash_owed >= 0.10) are too simplistic/wrong and need significant rework. Best to move to integer math.

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
  • "My crystal ball hints that the next version of C will specify decimal floating point numbers" Do you have a source for that? Without it, i think it is very unlikely, since it does not fit with the goal of C and it is a pain to implement in C on many platforms and has almost no practical use cases. – 12431234123412341234123 Sep 28 '20 at 14:58
  • @12431234123412341234123 Might you be a [bettin' man](https://en.wikipedia.org/wiki/C2x)? "decimal floating-point arithmetic" would likely be an optional feature. – chux - Reinstate Monica Sep 28 '20 at 15:39
-1

You don't need to convert from floating point to integer to get the program to work. From what I could see, the problem is that your program has no idea what to do once it gets to 0, probably because it never actually reaches absolute zero. One way to get around this is to add an additional else if statement that sets cash_owed to less than 0 whenever it gets less than 0.01:

    else if(cash_owed < 0.01)
    {
        cash_owed = -1;
    }

You also need to add a condition to the existing 0.01 else if statement:

    else if(cash_owed >= 0.01)
    {
        cash_owed -= 0.01;
        printf("Cash owed: %f\n", cash_owed);
        coins++;
        printf("Coins: %d\n", coins);
    }

So your while loop end up looking like this:

while(cash_owed > 0)
{

    if(cash_owed >= 0.25)
    {
        cash_owed -= 0.25;
        printf("Cash owed: %f\n", cash_owed);
        coins++;
        printf("Coins: %d\n", coins);
    }
    else if(cash_owed >= 0.10)
    {
        cash_owed -= 0.10;
        printf("Cash owed: %f\n", cash_owed);
        coins++;
        printf("Coins: %d\n", coins);
    }
    else if(cash_owed >= 0.05)
    {
        cash_owed -= 0.05;
        printf("Cash owed: %f\n", cash_owed);
        coins++;
        printf("Coins: %d\n", coins);
    }
    else if(cash_owed >= 0.01)
    {
        cash_owed -= 0.01;
        printf("Cash owed: %f\n", cash_owed);
        coins++;
        printf("Coins: %d\n", coins);
    }
    else if(cash_owed < 0.01)
    {
        cash_owed = -1;
    }
}

This should work as long as your user enters valid amounts (so you might want to add a check to make sure they don't add more than 2 decimals).

Bluejay
  • 47
  • 6
  • I am not your down-voter, but telling OP: _You don't need to convert from floating point to integer to get the program to work._ is an indication that you might be missing the point. From that point it would be very unlikely that your response would be on-point. (Which I do not thing it is.) Try reading the post, and its comments once more, then maybe edit your response :) – ryyker Sep 28 '20 at 13:53
  • Yeah sure, don't get y ppl downvote instead of telling what's wrong. Btw I just had to use round function to remove in accuracy for my project – user14354509 Sep 28 '20 at 14:17
  • Using `float` constants like `0.10f` to match `float cash` may reduce one class of problems. Using thresholds offset by 0.005 is also useful. Yet these are just a start needed to use FP math for money. – chux - Reinstate Monica Sep 28 '20 at 14:28
  • Starting with .07 (0.070000000298023223876953125 in `float cash_owed`), this code calculates 2 coins are needed, but the correct answer is 3 (1 nickel and 2 pennies). – Eric Postpischil Sep 28 '20 at 22:41