std::stringstream and floating point accuracy

Discussion in 'C++' started by Mr Fish, Oct 20, 2005.

  1. Mr Fish

    Mr Fish Guest

    Is it possible for me to record floats in a std::stringstream with
    100% accuracy? If so how?

    Here's a little prog that demonstrates how the default ss loses
    accuracy

    //-----------------------------------------------------------------------------
    #include <sstream>
    #include <iostream>
    using namespace std;

    int main()
    {

    stringstream ss;

    float fOriginal = 0.00000011920928955078125f;

    ss << fOriginal;

    float fRestored;
    ss >> fRestored;

    cout << endl << fOriginal;
    cout << endl << fRestored;

    cout << endl << endl << (fOriginal == fRestored); //should be
    equal but are not
    cout << endl << fOriginal - fRestored; //there's a diff!


    return 0;
    }

    //-----------------------------------------------------------------------------
     
    Mr Fish, Oct 20, 2005
    #1
    1. Advertising

  2. Mr Fish

    Kristo Guest

    Mr Fish wrote:
    > Is it possible for me to record floats in a std::stringstream with
    > 100% accuracy? If so how?


    Assuming you want to store a decimal number with a fixed number of
    places (i.e., a non-repeating rational number), the only way to ensure
    100% accuracy is to store it as a string.

    > Here's a little prog that demonstrates how the default ss loses
    > accuracy


    [snip code example]

    The problem is that representing decimals in a computer is inaccurate.
    It's not the stringstream's fault. Here's a good essay to read that
    will explain why:

    http://docs.sun.com/source/806-3568/ncg_goldberg.html

    Kristo
     
    Kristo, Oct 20, 2005
    #2
    1. Advertising

  3. Mr Fish wrote:
    >
    > Is it possible for me to record floats in a std::stringstream with
    > 100% accuracy? If so how?
    >
    > Here's a little prog that demonstrates how the default ss loses
    > accuracy
    >
    > //-----------------------------------------------------------------------------
    > #include <sstream>
    > #include <iostream>
    > using namespace std;
    >
    > int main()
    > {
    >
    > stringstream ss;
    >
    > float fOriginal = 0.00000011920928955078125f;
    >


    In most implementations I am aware of, float is capable of holding
    5 to 6 digits. Apply that to your number, and you get:

    1.19209 E -7

    everything else in your number is already lost. Even the 9 in the
    last digit is already a questionable one. Things get worse if you
    do sme arithmetic with that number.

    As a minimum: forget 'float' and start using 'double'.
    Unless you know what you do and are willing to do it and have the
    knowledge to do it and have a very, very, very good reason: never
    use float.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, Oct 20, 2005
    #3
  4. I tried the followind (in C) to test how much was lost when storing in a
    float:

    float x=0.00000011920928955078125f;
    printf("%.25f\n", x);

    The output is exactly:

    0.0000001192092895507812500

    Wow!!
    For some reason, Mr Fish chose a number which is exactly representable as a
    float var.

    Anyway, with arbitrary numbers like 0.00000012268758375648363f, the output
    is 0.0000001226875809834382400. You get 8 correct significant digits. But
    the correct digits is not the important thing, but the precision of the
    stored value, or the error of the representation.

    The error in that case is around -2.77e-15. If the original number
    represented a length of 12.2 cm (approx. the diameter of a CD) expressed in
    strange units like thousands of km [:)], the error would be equivalent to 3
    millionths of a millimeter, or around 30 times the diameter of a hydrogen
    atom. Is it that bad?

    Let's not just look at the written digits (in decimal), counting how many
    are right. Let's look at the accuracy of the values for a particular
    application. Decimal is just a representation, which can be as bad as
    binary, it's just a different one. We should not see a decimal
    representation as the perfect one.

    float is not that bad for many, many tasks, but double is sure more suitable
    for many others.


    "Karl Heinz Buchegger" <> escribió en el mensaje
    news:...
    > Mr Fish wrote:
    > >
    > > Is it possible for me to record floats in a std::stringstream with
    > > 100% accuracy? If so how?
    > >
    > > Here's a little prog that demonstrates how the default ss loses
    > > accuracy
    > >
    > >

    //--------------------------------------------------------------------------
    ---
    > > #include <sstream>
    > > #include <iostream>
    > > using namespace std;
    > >
    > > int main()
    > > {
    > >
    > > stringstream ss;
    > >
    > > float fOriginal = 0.00000011920928955078125f;
    > >

    >
    > In most implementations I am aware of, float is capable of holding
    > 5 to 6 digits. Apply that to your number, and you get:
    >
    > 1.19209 E -7
    >
    > everything else in your number is already lost. Even the 9 in the
    > last digit is already a questionable one. Things get worse if you
    > do sme arithmetic with that number.
    >
    > As a minimum: forget 'float' and start using 'double'.
    > Unless you know what you do and are willing to do it and have the
    > knowledge to do it and have a very, very, very good reason: never
    > use float.
    >
    > --
    > Karl Heinz Buchegger
    >
     
    Alvaro Segura, Oct 20, 2005
    #4
  5. Mr Fish

    Kai-Uwe Bux Guest

    Mr Fish wrote:

    > Is it possible for me to record floats in a std::stringstream with
    > 100% accuracy? If so how?


    Maybe you find something useful in the following snippet:

    #include <iostream>
    #include <limits>
    #include <cmath>
    #include <iomanip>

    template < typename Float >
    struct precision {

    static unsigned int digits ( unsigned int base ) {
    return( -
    std::log( std::numeric_limits<Float>::epsilon() )
    /
    std::log( base ) );
    }

    };

    template < typename Float >
    unsigned int sig_digits ( Float const & ) {
    return( precision<Float>::digits(10) );
    }

    int main ( void ) {
    std::cout << precision<float>::digits( 10 )
    << " "
    << precision<double>::digits( 10 )
    << '\n';
    float x = 2.3345467334234;
    double y = 12.230912093719823691836;
    std::cout << std::setprecision( sig_digits(x) ) << x << '\n';
    std::cout << std::setprecision( sig_digits(y) ) << y << '\n';
    }



    Best

    Kai-Uwe Bux
     
    Kai-Uwe Bux, Oct 21, 2005
    #5
  6. Alvaro Segura wrote:
    >
    > I tried the followind (in C) to test how much was lost when storing in a
    > float:
    >
    > float x=0.00000011920928955078125f;
    > printf("%.25f\n", x);
    >
    > The output is exactly:
    >
    > 0.0000001192092895507812500
    >
    > Wow!!
    > For some reason, Mr Fish chose a number which is exactly representable as a
    > float var.
    >
    > Anyway, with arbitrary numbers like 0.00000012268758375648363f, the output
    > is 0.0000001226875809834382400. You get 8 correct significant digits. But
    > the correct digits is not the important thing, but the precision of the
    > stored value, or the error of the representation.
    >
    > The error in that case is around -2.77e-15.


    That is the absolute error.
    Completely unimportant. Important is the relative error (the error in relation
    to the number)

    Add 1.0f to the number above and see what is left from your -2.77e-15

    I suggest you try the same thing with the number
    1.2268758375648363f (That's the same number, just a different exponent)
    and see if your figures also hold.


    > float is not that bad for many, many tasks, but double is sure more suitable
    > for many others.


    up to now you have only shown that storing some numbers in float variables
    is not that bad if all you do, is printing them.
    But that is not the usual thing you do with float, isn't it?
    Usually one does some arithmetic with numbers. The more arithmetic you
    do, the more things get worse.

    --
    Karl Heinz Buchegger
     
    Karl Heinz Buchegger, Oct 21, 2005
    #6
    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. KidLogik
    Replies:
    2
    Views:
    7,906
    Alberto Barbati
    Feb 24, 2004
  2. Jon Rea

    Floating Point Accuracy

    Jon Rea, Apr 6, 2006, in forum: C++
    Replies:
    8
    Views:
    653
    Walter Bright
    Apr 6, 2006
  3. Saraswati lakki
    Replies:
    0
    Views:
    1,411
    Saraswati lakki
    Jan 6, 2012
  4. teeshift
    Replies:
    2
    Views:
    290
    Chris Pearl
    Dec 1, 2006
  5. Steven D. Arnold

    floating point accuracy in JRuby

    Steven D. Arnold, Jun 18, 2009, in forum: Ruby
    Replies:
    3
    Views:
    106
    Tim Hunter
    Jun 18, 2009
Loading...

Share This Page