473,394 Members | 1,721 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,394 software developers and data experts.

Beginner question: Precision of floating point arithmetic...

Hello all,
I apologize as I am sure this has probably been dealth with before...
but I am doing an exercise from "Practical C Programming" and I have
been unable to get it to work perfectly due to problems with floating
point arithmetic and I am looking for a way to solve it. See the code
below...
Given a certain amount of change (below $1.00) the program will tell
you how many of each coin you will need to get that amount. The
program is "working" in that the logic appears correct and it DOES
work for some numbers, but for others, it is not. The problem appears
to be that 0.01 as I see it, is not being represented in memory.
I have done some searching online and I am sure this is a common
problem but I just can't seem to find the workaround...

Thank you for all your help...

Shawn

#include <stdio.h>

int main()
{
char input[100];
float total_input, running_total;
int quarters, nickels, dimes, pennies;

/* Zero out all the variables */
quarters = nickels = dimes = pennies = 0;
total_input = running_total = 0;

/* Get the necessary amount of change */
printf("Enter the total amount of change, less than $1.00: ");
fgets(input, sizeof(input), stdin);
sscanf(input, "%f", &total_input);

/* Loop until we get a sane amount */
while (total_input >= 1.00 || total_input <= 0.00) {
printf("Total is not between $0.00 and $1.00.\n");
printf("Enter the total amount of change, less than
$1.00: ");
fgets(input, sizeof(input), stdin);
sscanf(input, "%f", &total_input);
}

/* Store in another variable so we can use it */
running_total = total_input;

while (running_total >= 0.25) {
++quarters;
running_total -= 0.25;
}
while (running_total >= 0.10) {
++dimes;
running_total -= 0.10;
}
while (running_total >= 0.05) {
++nickels;
running_total -= 0.05;
}
while (running_total >= 0.01) {
++pennies;
running_total -= 0.01;
}

printf("In order to get $%.2f in change, you will need:\n",
total_input);
printf("%d quarters,\n", quarters);
printf("%d dimes,\n", dimes);
printf("%d nickels,\n", nickels);
printf("%d pennies\n", pennies);

return(0);
}
Nov 14 '05 #1
10 2226
Shawn wrote:
Hello all,
I apologize as I am sure this has probably been dealth with before...
but I am doing an exercise from "Practical C Programming" and I have
been unable to get it to work perfectly due to problems with floating
point arithmetic and I am looking for a way to solve it. See the code
below...
Given a certain amount of change (below $1.00) the program will tell
you how many of each coin you will need to get that amount. The
program is "working" in that the logic appears correct and it DOES
work for some numbers, but for others, it is not. The problem appears
to be that 0.01 as I see it, is not being represented in memory.
I have done some searching online and I am sure this is a common
problem but I just can't seem to find the workaround...


First, the question has, as you suspect, arisen before.
In fact, it arises frequently, and therefore has a place in
the comp.lang.c Frequently Asked Questions (FAQ) list

http://www.eskimo.com/~scs/C-faq/top.html

Start with Question 14.1, and then look at 14.4 and 14.5.

Once you've digested that, you'll have realized that
floating-point arithmetic is trickier than it first appears.
Floating-point is very good at dealing with proportions and
ratios and logarithms and the like, but is not well-suited
to counting problems -- problems involving discrete "things,"
if you like. So what's the work-around? Well, can you think
of a way to restate your original problem in terms of discrete
indivisible units instead of fractions of something-or-other?
Hint: What should your program do if someone asks for $0.14159
in change?

--
Er*********@sun.com

Nov 14 '05 #2

"Shawn" <sd****@codepiranha.org> wrote in message

#include <stdio.h>

int main()
{
char input[100];
float total_input, running_total;
int quarters, nickels, dimes, pennies;

/* Zero out all the variables */
quarters = nickels = dimes = pennies = 0;
total_input = running_total = 0;

/* Get the necessary amount of change */
printf("Enter the total amount of change, less than $1.00: ");
fgets(input, sizeof(input), stdin);
sscanf(input, "%f", &total_input);
You want to check your return from sscanf().
/* Loop until we get a sane amount */
while (total_input >= 1.00 || total_input <= 0.00) {
printf("Total is not between $0.00 and $1.00.\n");
printf("Enter the total amount of change, less than
$1.00: ");
fgets(input, sizeof(input), stdin);
sscanf(input, "%f", &total_input);
}

/* Store in another variable so we can use it */
running_total = total_input;

while (running_total >= 0.25) {
++quarters;
running_total -= 0.25;
}
Here's your problem. Floating point representation is not exact, so if the
user enters 0.50 theres no guarantee that this won't be represented
internally as 0.4999, which will mess up your logic.
In fact all floating point units use a binary base, so 0.50 and 0.25 can be
represented exactly, but 0.1 cannot be. So the problem isn't here but in the
similar block of code for the dimes, below.
while (running_total >= 0.10) {
++dimes;
running_total -= 0.10;
}
while (running_total >= 0.05) {
++nickels;
running_total -= 0.05;
}
while (running_total >= 0.01) {
++pennies;
running_total -= 0.01;
}

printf("In order to get $%.2f in change, you will need:\n",
total_input);
printf("%d quarters,\n", quarters);
printf("%d dimes,\n", dimes);
printf("%d nickels,\n", nickels);
printf("%d pennies\n", pennies);

return(0);
}

The solution is to convert your float value, input, into an integer number
of pennies (I thought you Americans used cents, but that's by the by).

To do this, multiply the float value by 100, then round by adding 0.5 and
calling floor(). Just multiplying by 100 risks the inaccuracy problem
because a value of x.9999 will be rounded down.
Nov 14 '05 #3
>I apologize as I am sure this has probably been dealth with before...
but I am doing an exercise from "Practical C Programming" and I have
been unable to get it to work perfectly due to problems with floating
point arithmetic and I am looking for a way to solve it. See the code
below...
Given a certain amount of change (below $1.00) the program will tell
you how many of each coin you will need to get that amount. The
Use integer quantities of cents. You may use a floating-point variable
to store this if you want.
program is "working" in that the logic appears correct and it DOES
work for some numbers, but for others, it is not. The problem appears
to be that 0.01 as I see it, is not being represented in memory.
There is no exact representation for 0.01 in binary floating point, nor
is there for most non-integer decimal numbers. (Think about representing
1/3 exactly in decimal). There *IS* a representation, just not an
exact one.
I have done some searching online and I am sure this is a common
problem but I just can't seem to find the workaround...


It's not exact. Learn to live with it. The world is also an analog
world with all sorts of floating-point measurements, and no measurement
is exact. Comparing two floating-point numbers for exact equality
is hazardous. How close two floating-point numbers have to be
(either by ratio or by absolute difference) generally should be
APPLICATION-DEPENDENT, and NOT depend on details like the number
of significant digits being used in the implementation. Example:
the GPS coordinates of two telephone poles are considered identical
(and to refer to the same pole) if they are within 20 feet of each
other, because GPS cannot reliably measure distances more accurately
than that, and besides, phone companies don't place poles that close
to each other.

One approach for money is to use the integer value 1 to represent the smallest
amount of money of interest (which for some applications might be a tenth
or thousandth of a cent in the USA). Of course, printing such a value
on checks needs to be done carefully.

Gordon L. Burditt
Nov 14 '05 #4
"Malcolm" <ma*****@55bank.freeserve.co.uk> writes:
[...]
The solution is to convert your float value, input, into an integer number
of pennies (I thought you Americans used cents, but that's by the by).


<OT>
A "cent" is a unit of currency equal to $0.01 (one hundredth of a
dollar). A "penny" is an informal name for the one-cent coin; the
term is also sometimes used as a synonym for "cent". Similarly,
"nickel" is the informal name for a five-cent coin. A "dime" is
actually a unit of currency equal to $0.10, or 10 cents, but these
days the term is used almost exclusively to refer to the 10-cent coin.
</OT>

--
Keith Thompson (The_Other_Keith) ks***@mib.org <http://www.ghoti.net/~kst>
San Diego Supercomputer Center <*> <http://users.sdsc.edu/~kst>
We must do something. This is something. Therefore, we must do this.
Nov 14 '05 #5
Eric Sosman <Er*********@sun.com> wrote:
Hint: What should your program do if someone asks for $0.14159
in change?


Sell him some more pie?

Richard
Nov 14 '05 #6
"Joona I Palaste" <pa*****@cc.helsinki.fi> wrote in message
news:cd**********@oravannahka.helsinki.fi...
[snip]
Similarly, I've heard that the British use "pence" to refer a monetary
sum, but "pennies" to refer to a collection of coins.


Yes. The coins are labeled "ONE PENNY". Paradoxically, older ones say "NEW
PENNY" :).

Alex
Nov 14 '05 #7
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Alex Fraser wrote:
"Joona I Palaste" <pa*****@cc.helsinki.fi> wrote in message
news:cd**********@oravannahka.helsinki.fi...
[snip]
Similarly, I've heard that the British use "pence" to refer a monetary
sum, but "pennies" to refer to a collection of coins.

Yes. The coins are labeled "ONE PENNY". Paradoxically, older ones say "NEW
PENNY" :).


And, what are the ones issued before 1971 called?
(hint: http://en.wikipedia.org/wiki/Pound_Sterling)

- --
Lew Pitcher
IT Consultant, Enterprise Application Architecture,
Enterprise Technology Solutions, TD Bank Financial Group

(Opinions expressed are my own, not my employers')
-----BEGIN PGP SIGNATURE-----
Version: GnuPG v1.2.4 (MingW32)

iD8DBQFA9tR1agVFX4UWr64RAs3gAJ40ryG1l3Owc1B2H73/D8HMuybuBwCg8qsZ
gsF5XJD9iUppsot0mwyD6GI=
=W7md
-----END PGP SIGNATURE-----
Nov 14 '05 #8
"Lew Pitcher" <Le*********@td.com> wrote in message
news:8u*********************@news20.bellglobal.com ...
-----BEGIN PGP SIGNED MESSAGE-----
Hash: SHA1

Alex Fraser wrote:
"Joona I Palaste" <pa*****@cc.helsinki.fi> wrote in message
news:cd**********@oravannahka.helsinki.fi...
[snip]
Similarly, I've heard that the British use "pence" to refer a monetary
sum, but "pennies" to refer to a collection of coins.

Yes. The coins are labeled "ONE PENNY". Paradoxically, older ones say
"NEW PENNY" :).


And, what are the ones issued before 1971 called?


Annoyingly large?

Alex
Nov 14 '05 #9
On Thu, 15 Jul 2004 15:01:12 -0400, in comp.lang.c , Lew Pitcher
<Le*********@td.com> wrote:
Alex Fraser wrote:

Yes. The coins are labeled "ONE PENNY". Paradoxically, older ones say "NEW
PENNY" :).


And, what are the ones issued before 1971 called?


One penny. symbol d.

Bonus points for remembering the value of a farthing, groat, tanner, half
dollar and pound scots. Without looking on wikipedia or google.

--
Mark McIntyre
CLC FAQ <http://www.eskimo.com/~scs/C-faq/top.html>
CLC readme: <http://www.angelfire.com/ms3/bchambless0/welcome_to_clc.html>
----== Posted via Newsfeed.Com - Unlimited-Uncensored-Secure Usenet News==----
http://www.newsfeed.com The #1 Newsgroup Service in the World! >100,000 Newsgroups
---= 19 East/West-Coast Specialized Servers - Total Privacy via Encryption =---
Nov 14 '05 #10
Joona I Palaste <pa*****@cc.helsinki.fi> wrote in message news:<cd**********@oravannahka.helsinki.fi>...
Keith Thompson <ks***@mib.org> scribbled the following:
"Malcolm" <ma*****@55bank.freeserve.co.uk> writes:
[...]
The solution is to convert your float value, input, into an integer number
of pennies (I thought you Americans used cents, but that's by the by).

<OT>
A "cent" is a unit of currency equal to $0.01 (one hundredth of a
dollar). A "penny" is an informal name for the one-cent coin; the
term is also sometimes used as a synonym for "cent". Similarly,
"nickel" is the informal name for a five-cent coin. A "dime" is
actually a unit of currency equal to $0.10, or 10 cents, but these
days the term is used almost exclusively to refer to the 10-cent coin.
</OT>


Similarly, I've heard that the British use "pence" to refer a monetary
sum, but "pennies" to refer to a collection of coins.


<OT>
A US penny is 1/100 of a dollar; a British penny (since 1971) is 1/100
of a pound. I figured the Brits used "pence" as the more traditional
plural, (e.g. there is an American music group with the name Sixpence
None The Richer), Americans use "pennies" or "cents" (as a penny is a
centidollar).

The U.S. mint produces six different general currency coin
denominations: penny ($.01), nickel ($.05) (so named because early
versions were made of nickel or a nickel alloy), dime ($.10) (the name
is from the French disme), quarter ($.25), half dollar ($.50), and
dollar coins ($1.00). The Mint also produces coins for numismatic
appeal, such as $20 gold coins, that are not generally used as
currency.
</OT>

Gregory Pietsch
Nov 14 '05 #11

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

24
by: Philipp | last post by:
Hello (not sure this is the right forum for that question so please redirect me if necessary) How can I know how many double values are available between 0 and 1? On my machine (pentium 3) I get...
4
by: Roger Leigh | last post by:
Hello, I'm writing a fixed-precision floating point class, based on the ideas in the example fixed_pt class in the "Practical C++ Programming" book by Steve Oualline (O' Reilly). This uses a...
8
by: Benedikt Wismans | last post by:
dear group! <script language="javascript"> var a = 60381.11; var b = 1437261.58; var c = a + b; alert (c); -> 1497642.6900000002 var a = 60381.11; var b = 1437261.50;
16
by: BigMan | last post by:
How can I check if assignment of a float to a double (or vice versa) will result in loss of precision?
3
by: Madan | last post by:
Hi all, I had problem regarding float/double arithmetic only with + and - operations, which gives inaccurate precisions. I would like to know how the arithmetic operations are internally handled...
8
by: Grant Edwards | last post by:
I'm pretty sure the answer is "no", but before I give up on the idea, I thought I'd ask... Is there any way to do single-precision floating point calculations in Python? I know the various...
7
by: GCRhoads | last post by:
I'm looking for a very basic high-precision arithmetic library. I need to be able to specify a fixed number of bits or decimal digits (32 decimal digits should be all I need). The only arithmetic...
137
by: mathieu.dutour | last post by:
Dear all, I want to do multiprecision floating point, i.e. I want to go beyond single precision, double precision and have quadruple precision, octuple precision and the like, and possibly with...
0
by: Charles Coldwell | last post by:
James Kanze <james.kanze@gmail.comwrites: True, with some additional considerations. The commonly used IEEE 754 floating point formats are single precision: 32 bits including 1 sign bit, 23...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.