updated for accuracy and completeness
You are encountering is a (rather common) problem of precision in floating point numbers. On many compilers, floating point numbers are only 32 bits long, and they use a certain number of those bits (23) for their "significand" (sometimes referred to as "mantissa"), 1 sign bit, and 8 bits for the "exponent" (in a number like 1.23E45, the "1.23" is the significand, and the "45" is the exponent. In binary, you actually have relatively few (24) ones and zeros available so you run out of precision at around digit 6 or 7 in decimal notation).
To illustrate this loss of precision, I wrote a few lines of code:
#include <stdio.h>
int main(){
float fpennies;
long lpennies, ii;
lpennies = 805306360;
for(ii = 0; ii< 100; ii++) {
fpennies = lpennies + ii;
printf("%ld pennies converted to float: %.0f fpennies\n",ii+ lpennies, fpennies);
}
}
This produced many lines of the type
805306360 pennies converted to float: 805306368 fpennies
805306361 pennies converted to float: 805306368 fpennies
805306362 pennies converted to float: 805306368 fpennies
...
805306400 pennies converted to float: 805306368 fpennies
805306401 pennies converted to float: 805306432 fpennies
As you can see, right around 805306400
, incrementing the long
by just one increments the float
representation of the number by 64
! This is best explained by looking at the binary representation of the floating point number a little closer.
First, here is the organization of a 32 bit floating point number (from http://upload.wikimedia.org/wikipedia/commons/d/d2/Float_example.svg):

We can get the hex representation of a number with some explicit casting:
printf("%.0f %08x", fpennies, *(unsigned int*)(&fpennies));
For the two values that spanned the jump we saw earlier, this results in
805306368 4e400000
805306432 4e400001
As you can see, the "least significant bit" of the significand increased by 1
, but the exponent implies a multiplier of 64. Why 64? Well, let's expand the top few bits:
0x4e40 = 0100 1110 0100 0000 in binary
Since the top bit is the sign bit (0 = positive), and the next eight bits are the exponent, this makes the exponent
1001 1100 = 0x9c = 156
Now the rule for getting from the bits in the floating point to its value (see http://en.wikipedia.org/wiki/Single-precision_floating-point_format ) is
value = (-1)^(sign bit) * (1 + sum(i=1 to 23, bit(23-i)*2^(-i))) * 2^(exponent - 127)
In this case, an change of 1
in the least significant bit (bit 0) adds 2^(-23) * 2^( 156 - 127 ) = 2^6 = 64
Thus, for numbers of this magnitude, the smallest step that can be represented is 64
, as you see in the output.
If you want to get around this problem, you can do the thing suggested in Vaughn's answer - work with long integers representing pennies, and using integer math (division, modulo) to obtain the "whole dollars, whole cents" amount.
long int dollars, cents, pennies;
...
dollars = pennies / 100;
cents = pennies % 100;
In this way you can represent some pretty big sums of money without loss of precision.
In practice, when you write
float pennies = 805306365;
printf("you have %f pennies\n", pennies);
You get
You have 805306368 pennies
If you use a double
type you will have better luck (in this case).