Zeiss Ikon
Zeiss Ikon

Reputation: 481

Conversion of float to int changes the value

I've looked at this question, and it doesn't appear to be the same situation.

I have a function in the check register program I'm writing that reads in a dollar amount from the user, validates it wasn't entered with fractional cents, and checks with the user that it was entered correctly. What I'm getting, though, is that after multiplying the float value that was entered by 100 and truncating with (int), the value changes. For instance, if I enter 1118.58, I can (via debug printf statements) verify that 1118.58 was scanned and assigned to amt correctly, and my while conditional (int)100 * amt == 100 * amt is correctly testing as TRUE, but after conversion to integer, the integer value is stored as 111857. More perplexing, it doesn't happen with every value (though I'm just getting going well on testing, this is the first entry I've seen change this way).

I'm using gcc on Kubuntu 14.04 64-bit, with C99 standard setting in my compile command. Here's the function that's giving the problem (presuming you don't want/need to see 1300 lines of the complete program). Note: I have Boolean values and operators defined in a header file for my convenience -- I've recently discovered there's a standard way to do that, but haven't converted my header file yet.

int get_amt (void)
{
  float amt;
  int scanned, i_amt;
  int success = FALSE;
  char yn = '\0';

  while (NOT success)
  {
    scanned = scanf("%f%*c", &amt);

    /* validate and verify amount */
    if (scanned >= 1 AND (int)100*amt == 100*amt AND amt <= 100000)
    {
      i_amt = (int)(100 * amt);
      printf("\n amt = %4.2f i_amt = %i", amt, i_amt);
      printf("\nYou entered $%i.%.2i -- Correct (Y/n)?", i_amt/100, i_amt%100);
      scanf("%c%*c", &yn);
      if (yn == '\0' OR yn == 'Y' OR yn == 'y')
        success = TRUE;
    }
  }
  return (i_amt);
}

And here's an output sample with the debug print statement:

Enter deposit amount (dollars and cents): $ 1118.58                             

 amt = 1118.58 i_amt = 111857                                                   
You entered $1118.57 -- Correct (Y/n)?                                          

Why is this happening, and how do I fix it?

After discussion in the comments below, I've converted the function to use integers, so there's no question of float precision (I hadn't really thought about just how little precision a standard float has on a 64-bit OS and compiler). Here's the updated version, which can't give this failure because there are no floats:

int get_amt (void)
{
  int scanned, amt1, amt2;
  int success = FALSE;
  char yn = '\0';

  while (NOT success)
  {
    scanned = scanf("%i.%i%*c", &amt1, &amt2);

    /* validate and verify amount */
    if (scanned >= 1)
    {
      printf("\nYou entered $%i.%.2i -- Correct (Y/n)?", amt1, amt2);
      scanf("%c%*c", &yn);
      if (yn == '\0' OR yn == 'Y' OR yn == 'y')
    success = TRUE;
    }
  }
  return (100*amt1 + amt2);
}

Upvotes: 1

Views: 610

Answers (1)

wolfPack88
wolfPack88

Reputation: 4203

As @MitchWheat has already alluded to in a comment above, it is likely that when you print out the float, it rounds up, whereas when you calculate the int, it simply truncates. Get around this by using the round function. I.e., i_amt = round(100 * amt);, which will round the number in the same manner as the float is rounded.

Upvotes: 5

Related Questions