Floating point rounding error

Discussion in 'C Programming' started by Mukesh_Singh_Nick@yahoo.com, Jun 16, 2007.

  1. Guest

    Why does floating point have a rounding error? How to work around it?

    For example, the following:

    flaot f = 1234.12345678F;

    printf("%2f\n", f) //prints 1234.123413

    and

    printf("%8.9f\n", f) //prints 1234.123413086
    , Jun 16, 2007
    #1
    1. Advertising

  2. Flash Gordon Guest

    wrote, On 16/06/07 11:49:
    > Why does floating point have a rounding error?


    Calculate 2/3 as a decimal number. Come back when you have understood
    the answer to your question or when you have finished writing it without
    any rounding or truncation. I'll even get you started 0.6667 (I've
    rounded it here).

    > How to work around it?


    Use sufficient care and analysis for the problem at hand. This is a
    general problem, not a C specific one, so comp.programming, and there is
    no one correct solution for all situations.
    --
    Flash Gordon
    Flash Gordon, Jun 16, 2007
    #2
    1. Advertising

  3. said:

    > Why does floating point have a rounding error?


    Consider 1234.12345678

    It's easy enough to deal with 1234. Here are the bits: 10011010010

    So let's try to deal with 0.12345678, using binary notation.

    So 0.1 (binary) is 0.5 (decimal), 0.01 (binary) is 0.25 (decimal), and
    so on.
    0.1 = 1/2 = 0.5 - too large
    0.01 = 1/4 = 0.25 - too large
    0.001 = 1/8 = 0.125 - too large
    0.0001 = 1/16 = 0.0625 - too small
    0.00011 = 3/32 = 0.09375 - too small
    0.000111 = 7/64 = 0.109375 - too small
    0.0001111 = 15/128 = 0.1171875 - too small
    0.00011111 = 31/256 = 0.12109375 - too small
    0.000111111 = 63/512 = 0.123046875 - too small
    0.0001111111 = 127/1024 = 0.1240234375 - too large
    0.00011111101 = 253/2048 = 0.12353515625 - too large
    0.000111111001 = 505/4096 = 0.123291015625 - too small
    0.0001111110011 = 1011/8192 = 0.1234130859375 - too small
    0.00011111100111 = 2023/16384 = 0.12347412109375 - too large
    0.000111111001101 = 4045/32768 = 0.123443603515625 - too small
    0.0001111110011011 = 8091/65536 = 0.1234588623046875 - too large

    So far, we've used 16 bits on this. Keep on calculatin', and find out
    how many bits you need if you're to get an *exact* representation of
    0.12345678. You might well be surprised by the result.

    > How to work around it?


    That depends on what you want to achieve.

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Jun 16, 2007
    #3
  4. Guest

    On Jun 16, 4:32 pm, Richard Heathfield <> wrote:
    > said:
    >
    > > Why does floating point have a rounding error?

    >
    > Consider 1234.12345678
    >
    > It's easy enough to deal with 1234. Here are the bits: 10011010010
    >
    > So let's try to deal with 0.12345678, using binary notation.
    >
    > So 0.1 (binary) is 0.5 (decimal), 0.01 (binary) is 0.25 (decimal), and
    > so on.
    > 0.1 = 1/2 = 0.5 - too large
    > 0.01 = 1/4 = 0.25 - too large
    > 0.001 = 1/8 = 0.125 - too large
    > 0.0001 = 1/16 = 0.0625 - too small
    > 0.00011 = 3/32 = 0.09375 - too small
    > 0.000111 = 7/64 = 0.109375 - too small
    > 0.0001111 = 15/128 = 0.1171875 - too small
    > 0.00011111 = 31/256 = 0.12109375 - too small
    > 0.000111111 = 63/512 = 0.123046875 - too small
    > 0.0001111111 = 127/1024 = 0.1240234375 - too large
    > 0.00011111101 = 253/2048 = 0.12353515625 - too large
    > 0.000111111001 = 505/4096 = 0.123291015625 - too small
    > 0.0001111110011 = 1011/8192 = 0.1234130859375 - too small
    > 0.00011111100111 = 2023/16384 = 0.12347412109375 - too large
    > 0.000111111001101 = 4045/32768 = 0.123443603515625 - too small
    > 0.0001111110011011 = 8091/65536 = 0.1234588623046875 - too large
    >
    > So far, we've used 16 bits on this. Keep on calculatin', and find out
    > how many bits you need if you're to get an *exact* representation of
    > 0.12345678. You might well be surprised by the result.
    >
    > > How to work around it?

    >
    > That depends on what you want to achieve.
    >
    > --
    > Richard Heathfield
    > "Usenet is a strange place" - dmr 29/7/1999http://www.cpax.org.uk
    > email: rjh at the above domain, - www.



    Thank you for replying with a very elaborate example, Richard. I would
    disappoint you if I told you I am intrigued by the representation of
    non-integral decimal numbers in their binary form.

    I know binary arithmetic with integrals. I sometimes wondered and
    never bothered myself as to how decimals were represented as binaries.
    I want to understand your example.

    I can see a pattern in the representation.

    0.1 is half.
    0.01 is a right shift and you further halve it.
    0.001 two right shifts further halving it and so on.

    You lost me at 0.011. Can I please request you to explain.
    , Jun 16, 2007
    #4
  5. said:

    <snip>

    > I know binary arithmetic with integrals. I sometimes wondered and
    > never bothered myself as to how decimals were represented as binaries.


    The representation of floating-point numbers is implementation-defined.
    IEEE 754 is common but not universal.

    > I want to understand your example.
    >
    > I can see a pattern in the representation.
    >
    > 0.1 is half.
    > 0.01 is a right shift and you further halve it.
    > 0.001 two right shifts further halving it and so on.
    >
    > You lost me at 0.011. Can I please request you to explain.


    You understand binary integers. Extend the concept.

    13 in binary is 1101 (1 * eight + 1 * four + 0 * two + 1 * one).

    So each column represents a multiplier half as big as that of the column
    to its left.

    So we might reasonably think of the columns beyond the binary point as
    representing a half, a quarter, an eighth, etc.

    So 0.11 would be (half + quarter) = (three-quarters) = 0.75

    0.011 would be (quarter + eighth) = (three-eighths) = 0.375

    and so on.

    That isn't necessarily how they're stored internally, of course, but it
    does give you a good idea of the number of bits you need for storing a
    particular value to a particular precision. I recommend that you read
    http://docs.sun.com/source/806-3568/ncg_goldberg.html

    (Title: "What Every Computer Scientist Should Know About Floating-Point
    Arithmetic")

    --
    Richard Heathfield
    "Usenet is a strange place" - dmr 29/7/1999
    http://www.cpax.org.uk
    email: rjh at the above domain, - www.
    Richard Heathfield, Jun 16, 2007
    #5
  6. Eric Sosman Guest

    wrote:
    > Why does floating point have a rounding error?


    Knowledge of the Great Mysteries is reserved for those
    who are worthy. To prove your worth, you must undertake a
    Quest and complete it successfully. Your Quest, Mukesh, is
    to discover what fraction one day is of one week, and express
    the answer as a decimal number, using as many decimal places
    as are needed for perfect accuracy. When you have done this
    I will know you are indeed worthy, and I will reveal to you
    the secret origin of rounding errors.

    --
    Eric Sosman
    lid
    Eric Sosman, Jun 16, 2007
    #6
  7. Guest

    On Jun 16, 4:53 pm, Richard Heathfield <> wrote:
    > said:
    >
    > <snip>
    >
    > > I know binary arithmetic with integrals. I sometimes wondered and
    > > never bothered myself as to how decimals were represented as binaries.

    >
    > The representation of floating-point numbers is implementation-defined.
    > IEEE 754 is common but not universal.
    >
    > > I want to understand your example.

    >
    > > I can see a pattern in the representation.

    >
    > > 0.1 is half.
    > > 0.01 is a right shift and you further halve it.
    > > 0.001 two right shifts further halving it and so on.

    >
    > > You lost me at 0.011. Can I please request you to explain.

    >
    > You understand binary integers. Extend the concept.
    >
    > 13 in binary is 1101 (1 * eight + 1 * four + 0 * two + 1 * one).
    >
    > So each column represents a multiplier half as big as that of the column
    > to its left.
    >
    > So we might reasonably think of the columns beyond the binary point as
    > representing a half, a quarter, an eighth, etc.
    >
    > So 0.11 would be (half + quarter) = (three-quarters) = 0.75
    >
    > 0.011 would be (quarter + eighth) = (three-eighths) = 0.375
    >
    > and so on.
    >
    > That isn't necessarily how they're stored internally, of course, but it
    > does give you a good idea of the number of bits you need for storing a
    > particular value to a particular precision. I recommend that you readhttp://docs.sun.com/source/806-3568/ncg_goldberg.html
    >
    > (Title: "What Every Computer Scientist Should Know About Floating-Point
    > Arithmetic")
    >
    > --
    > Richard Heathfield
    > "Usenet is a strange place" - dmr 29/7/1999http://www.cpax.org.uk
    > email: rjh at the above domain, - www.



    Thank you so very much, Richard. You just taught me something
    *fantabulous*. I just learnt something terrific, something I could not
    have learnt reading a thousand words. Actually, I think I've just
    understood the IEEE 754-1985 implementation in a nutshell.

    Is this rule of representing decimals in binary applicable only to
    754?

    And then I revisited your previous table wherein you try to reach a
    precision for 1234.12345678 by heuristic computation. It suddenly
    removed a big block in my head.

    Thank you, everyday.
    , Jun 16, 2007
    #7
  8. Guest

    I recommend that you readhttp://docs.sun.com/source/806-3568/ncg_goldberg.html
    >
    > (Title: "What Every Computer Scientist Should Know About Floating-Point
    > Arithmetic")
    >
    > --
    > Richard Heathfield
    > "Usenet is a strange place" - dmr 29/7/1999http://www.cpax.org.uk
    > email: rjh at the above domain, - www.



    Thank you. I certainly will.
    , Jun 16, 2007
    #8
  9. Joe Wright Guest

    wrote:
    > On Jun 16, 4:32 pm, Richard Heathfield <> wrote:
    >> said:
    >>
    >>> Why does floating point have a rounding error?

    >> Consider 1234.12345678
    >>
    >> It's easy enough to deal with 1234. Here are the bits: 10011010010
    >>
    >> So let's try to deal with 0.12345678, using binary notation.
    >>
    >> So 0.1 (binary) is 0.5 (decimal), 0.01 (binary) is 0.25 (decimal), and
    >> so on.
    >> 0.1 = 1/2 = 0.5 - too large
    >> 0.01 = 1/4 = 0.25 - too large
    >> 0.001 = 1/8 = 0.125 - too large
    >> 0.0001 = 1/16 = 0.0625 - too small
    >> 0.00011 = 3/32 = 0.09375 - too small
    >> 0.000111 = 7/64 = 0.109375 - too small
    >> 0.0001111 = 15/128 = 0.1171875 - too small
    >> 0.00011111 = 31/256 = 0.12109375 - too small
    >> 0.000111111 = 63/512 = 0.123046875 - too small
    >> 0.0001111111 = 127/1024 = 0.1240234375 - too large
    >> 0.00011111101 = 253/2048 = 0.12353515625 - too large
    >> 0.000111111001 = 505/4096 = 0.123291015625 - too small
    >> 0.0001111110011 = 1011/8192 = 0.1234130859375 - too small
    >> 0.00011111100111 = 2023/16384 = 0.12347412109375 - too large
    >> 0.000111111001101 = 4045/32768 = 0.123443603515625 - too small
    >> 0.0001111110011011 = 8091/65536 = 0.1234588623046875 - too large
    >>
    >> So far, we've used 16 bits on this. Keep on calculatin', and find out
    >> how many bits you need if you're to get an *exact* representation of
    >> 0.12345678. You might well be surprised by the result.
    >>
    >>> How to work around it?

    >> That depends on what you want to achieve.
    >>
    >> --
    >> Richard Heathfield
    >> "Usenet is a strange place" - dmr 29/7/1999http://www.cpax.org.uk
    >> email: rjh at the above domain, - www.

    >
    >
    > Thank you for replying with a very elaborate example, Richard. I would
    > disappoint you if I told you I am intrigued by the representation of
    > non-integral decimal numbers in their binary form.
    >
    > I know binary arithmetic with integrals. I sometimes wondered and
    > never bothered myself as to how decimals were represented as binaries.
    > I want to understand your example.
    >
    > I can see a pattern in the representation.
    >
    > 0.1 is half.
    > 0.01 is a right shift and you further halve it.
    > 0.001 two right shifts further halving it and so on.
    >
    > You lost me at 0.011. Can I please request you to explain.
    >

    Here's something to chew on..

    00111111 10111111 10011010 11011101 00010000 10010001 11001000 10010101
    Exp = 1019 (-3)
    111 11111101
    Man = .11111 10011010 11011101 00010000 10010001 11001000 10010101
    1.2345678000000000e-01

    I hope it didn't wrap on you.

    --
    Joe Wright
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
    Joe Wright, Jun 16, 2007
    #9
  10. CBFalconer Guest

    wrote:
    >
    > Why does floating point have a rounding error? How to work around
    > it? For example, the following:
    >
    > flaot f = 1234.12345678F;
    > printf("%2f\n", f) //prints 1234.123413
    > and
    > printf("%8.9f\n", f) //prints 1234.123413086


    It doesn't have a rounding error. It has a precision limit.

    --
    <http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
    <http://www.securityfocus.com/columnists/423>
    <http://www.aaxnet.com/editor/edit043.html>
    cbfalconer at maineline dot net



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Jun 16, 2007
    #10
  11. CBFalconer Guest

    Eric Sosman wrote:
    > wrote:
    >
    >> Why does floating point have a rounding error?

    >
    > Knowledge of the Great Mysteries is reserved for those
    > who are worthy. To prove your worth, you must undertake a
    > Quest and complete it successfully. Your Quest, Mukesh, is
    > to discover what fraction one day is of one week, and express
    > the answer as a decimal number, using as many decimal places
    > as are needed for perfect accuracy. When you have done this
    > I will know you are indeed worthy, and I will reveal to you
    > the secret origin of rounding errors.


    Easy. Just use a septal base (which is not decimal), get 0.1.
    :) (Very useful for writing lock combinations).

    --
    <http://www.cs.auckland.ac.nz/~pgut001/pubs/vista_cost.txt>
    <http://www.securityfocus.com/columnists/423>
    <http://www.aaxnet.com/editor/edit043.html>
    cbfalconer at maineline dot net



    --
    Posted via a free Usenet account from http://www.teranews.com
    CBFalconer, Jun 16, 2007
    #11
  12. Joe Wright Guest

    CBFalconer wrote:
    > wrote:
    >> Why does floating point have a rounding error? How to work around
    >> it? For example, the following:
    >>
    >> flaot f = 1234.12345678F;
    >> printf("%2f\n", f) //prints 1234.123413
    >> and
    >> printf("%8.9f\n", f) //prints 1234.123413086

    >
    > It doesn't have a rounding error. It has a precision limit.
    >


    Indeed. 1.23412341e+03 is all there is in 32 bits.

    --
    Joe Wright
    "Everything should be made as simple as possible, but not simpler."
    --- Albert Einstein ---
    Joe Wright, Jun 16, 2007
    #12
  13. Eric Sosman Guest

    [OT] Re: Floating point rounding error

    CBFalconer wrote:
    > Eric Sosman wrote:
    >> wrote:
    >>
    >>> Why does floating point have a rounding error?

    >> Knowledge of the Great Mysteries is reserved for those
    >> who are worthy. To prove your worth, you must undertake a
    >> Quest and complete it successfully. Your Quest, Mukesh, is
    >> to discover what fraction one day is of one week, and express
    >> the answer as a decimal number, using as many decimal places
    >> as are needed for perfect accuracy. When you have done this
    >> I will know you are indeed worthy, and I will reveal to you
    >> the secret origin of rounding errors.

    >
    > Easy. Just use a septal base (which is not decimal), get 0.1.
    > :) (Very useful for writing lock combinations).


    Since "as a decimal number" was clearly specified in the
    rules of the Quest, your change of base is not septal but septic.
    I'll have to look up the traditional rules for punishment of
    failure. "Something lingering, with boiling oil in it, I fancy.
    Something of that sort. I think boiling oil occurs in it, but
    I'm not sure. I know it's something humorous, but lingering,
    with either boiling oil or melted lead."

    AND you'll never get to learn about rounding error. Nyaahh!

    --
    Eric Sosman
    lid
    Eric Sosman, Jun 16, 2007
    #13
  14. Groovy hepcat was jivin' on Sat, 16 Jun
    2007 05:07:47 -0700 in comp.lang.c.
    Re: Floating point rounding error's a cool scene! Dig it!

    >On Jun 16, 4:53 pm, Richard Heathfield <> wrote:
    >> said:

    >
    >> The representation of floating-point numbers is implementation-defined.
    >> IEEE 754 is common but not universal.
    >>
    >> > I want to understand your example.

    >>
    >> > I can see a pattern in the representation.

    >>
    >> > 0.1 is half.
    >> > 0.01 is a right shift and you further halve it.
    >> > 0.001 two right shifts further halving it and so on.

    >>
    >> > You lost me at 0.011. Can I please request you to explain.

    >>
    >> You understand binary integers. Extend the concept.
    >>
    >> 13 in binary is 1101 (1 * eight + 1 * four + 0 * two + 1 * one).
    >>
    >> So each column represents a multiplier half as big as that of the column
    >> to its left.
    >>
    >> So we might reasonably think of the columns beyond the binary point as
    >> representing a half, a quarter, an eighth, etc.
    >>
    >> So 0.11 would be (half + quarter) = (three-quarters) = 0.75
    >>
    >> 0.011 would be (quarter + eighth) = (three-eighths) = 0.375
    >>
    >> and so on.

    >
    >Is this rule of representing decimals in binary applicable only to
    >754?


    This doesn't represent decimals. It represents values. Values are
    neither decimal nor binary, but may be expressed in decimal or binary
    or, indeed, any other number system, such as hexadecimal or octal. A
    computer stores values expressed internally in binary, but may read in
    or write out the values in decimal or other systems.
    What Richard showed you is not a complete floating point
    representation. It was simply a binary representation of a value. This
    is refered to as "fixed point". Floating point representations have a
    mantissa part and an exponent part. These parts are (typically)
    expressed in binary. For example, instead of representing .75 as .11
    in fixed point binary, it might be represented as (just to keep things
    simple) an 8 bit binary mantissa, 00000011, and an 8 bit exponent,
    11111110 (that's -2 expressed as an 8 bit binary number). This
    represents 3 * 2 ** -2 (using ** for exponentiation) or 3 >> 2. Real
    floating point implementations, however, use more bits for the
    mantissa and exponent, often with separate sign bits.

    --

    Dig the even newer still, yet more improved, sig!

    http://alphalink.com.au/~phaywood/
    "Ain't I'm a dog?" - Ronny Self, Ain't I'm a Dog, written by G. Sherry & W. Walker.
    I know it's not "technically correct" English; but since when was rock & roll "technically correct"?
    Peter 'Shaggy' Haywood, Jun 20, 2007
    #14
  15. On Sat, 16 Jun 2007 08:05:28 -0400, Eric Sosman
    <> wrote:

    > wrote:
    > > Why does floating point have a rounding error?

    >
    > Knowledge of the Great Mysteries is reserved for those
    > who are worthy. To prove your worth, you must undertake a
    > Quest and complete it successfully. Your Quest, Mukesh, is
    > to discover what fraction one day is of one week, and express
    > the answer as a decimal number, using as many decimal places
    > as are needed for perfect accuracy. When you have done this
    > I will know you are indeed worthy, and I will reveal to you
    > the secret origin of rounding errors.


    <OT> Didn't the French Revolution, among its many variously intriguing
    and alarming ideas, (try to) change the week to 10 days? </>

    - formerly david.thompson1 || achar(64) || worldnet.att.net
    David Thompson, Jul 1, 2007
    #15
  16. David Thompson <> writes:

    > On Sat, 16 Jun 2007 08:05:28 -0400, Eric Sosman
    > <> wrote:
    >
    > > wrote:
    > > > Why does floating point have a rounding error?

    > >
    > > Knowledge of the Great Mysteries is reserved for those
    > > who are worthy. To prove your worth, you must undertake a
    > > Quest and complete it successfully. Your Quest, Mukesh, is
    > > to discover what fraction one day is of one week, and express
    > > the answer as a decimal number, using as many decimal places
    > > as are needed for perfect accuracy. When you have done this
    > > I will know you are indeed worthy, and I will reveal to you
    > > the secret origin of rounding errors.

    >
    > <OT> Didn't the French Revolution, among its many variously intriguing
    > and alarming ideas, (try to) change the week to 10 days? </>


    Right. This calendar was in use 13 years or so.

    Yours,

    --
    Jean-Marc
    Jean-Marc Bourguet, Jul 2, 2007
    #16
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Sooha Park Lee

    Rounding a floating point number declared in "double"

    Sooha Park Lee, Jul 16, 2003, in forum: C Programming
    Replies:
    2
    Views:
    480
    Mark McIntyre
    Jul 16, 2003
  2. Sooha Park Lee

    Rounding a floating point number declared in "double"

    Sooha Park Lee, Jul 16, 2003, in forum: C Programming
    Replies:
    2
    Views:
    319
    martinh
    Jul 17, 2003
  3. Keflavich
    Replies:
    13
    Views:
    678
    J. Robertson
    Dec 14, 2007
  4. Saraswati lakki
    Replies:
    0
    Views:
    1,318
    Saraswati lakki
    Jan 6, 2012
  5. Roger Pack

    floating point rounding error?

    Roger Pack, Feb 21, 2009, in forum: Ruby
    Replies:
    8
    Views:
    134
    Raphael Clancy
    Feb 22, 2009
Loading...

Share This Page