number of digits in a number

Discussion in 'C++' started by bejiz, Sep 26, 2007.

  1. bejiz

    bejiz Guest

    Hi,
    Do you know a way to tell to the compiler that if
    there are numbers of 1 digit ( 2, 6, 8,...), I want spaces like this:
    " ".
    But if I have numbers of 3 digits, I want spaces
    like this: " ".
    I don't know how to get the numbers of digits in
    a number (integer or float).
    Thanks.
     
    bejiz, Sep 26, 2007
    #1
    1. Advertising

  2. bejiz wrote:
    > Hi,
    > Do you know a way to tell to the compiler that if
    > there are numbers of 1 digit ( 2, 6, 8,...), I want spaces like this:
    > " ".
    > But if I have numbers of 3 digits, I want spaces
    > like this: " ".
    > I don't know how to get the numbers of digits in
    > a number (integer or float).


    Number of digits in 'x' (assuming 'x' is unsigned) :

    int ndigits = x > 0 ? int(log10(x)) + 1 : 1;

    As to preceding number of spaces, see 'setw' stream manipulator.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 26, 2007
    #2
    1. Advertising

  3. bejiz

    Mark P Guest

    Victor Bazarov wrote:
    > bejiz wrote:
    >> Hi,
    >> Do you know a way to tell to the compiler that if
    >> there are numbers of 1 digit ( 2, 6, 8,...), I want spaces like this:
    >> " ".
    >> But if I have numbers of 3 digits, I want spaces
    >> like this: " ".
    >> I don't know how to get the numbers of digits in
    >> a number (integer or float).

    >
    > Number of digits in 'x' (assuming 'x' is unsigned) :
    >
    > int ndigits = x > 0 ? int(log10(x)) + 1 : 1;
    >
    > As to preceding number of spaces, see 'setw' stream manipulator.
    >
    > V


    Maybe the standard guarantees otherwise, but this seems potentially
    susceptible to numerical inaccuracies. What happens if log10( 100)
    returns 1.99999999987?
     
    Mark P, Sep 26, 2007
    #3
  4. Mark P wrote:
    > Victor Bazarov wrote:
    >> bejiz wrote:
    >>> Hi,
    >>> Do you know a way to tell to the compiler that
    >>> if there are numbers of 1 digit ( 2, 6, 8,...), I want spaces like
    >>> this: " ".
    >>> But if I have numbers of 3 digits, I want spaces
    >>> like this: " ".
    >>> I don't know how to get the numbers of digits in
    >>> a number (integer or float).

    >>
    >> Number of digits in 'x' (assuming 'x' is unsigned) :
    >>
    >> int ndigits = x > 0 ? int(log10(x)) + 1 : 1;
    >>
    >> As to preceding number of spaces, see 'setw' stream manipulator.
    >>
    >> V

    >
    > Maybe the standard guarantees otherwise, but this seems potentially
    > susceptible to numerical inaccuracies. What happens if log10( 100)
    > returns 1.99999999987?


    Right. I should have added 0.5:

    int ndigits = x > 0 ? int(log10(x + 0.5)) + 1 : 1;

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 27, 2007
    #4
  5. bejiz

    Mark P Guest

    Victor Bazarov wrote:
    > Mark P wrote:
    >> Victor Bazarov wrote:
    >>> bejiz wrote:
    >>>> Hi,
    >>>> Do you know a way to tell to the compiler that
    >>>> if there are numbers of 1 digit ( 2, 6, 8,...), I want spaces like
    >>>> this: " ".
    >>>> But if I have numbers of 3 digits, I want spaces
    >>>> like this: " ".
    >>>> I don't know how to get the numbers of digits in
    >>>> a number (integer or float).
    >>> Number of digits in 'x' (assuming 'x' is unsigned) :
    >>>
    >>> int ndigits = x > 0 ? int(log10(x)) + 1 : 1;
    >>>
    >>> As to preceding number of spaces, see 'setw' stream manipulator.
    >>>
    >>> V

    >> Maybe the standard guarantees otherwise, but this seems potentially
    >> susceptible to numerical inaccuracies. What happens if log10( 100)
    >> returns 1.99999999987?

    >
    > Right. I should have added 0.5:
    >
    > int ndigits = x > 0 ? int(log10(x + 0.5)) + 1 : 1;
    >
    > V


    That works, and also spares you the indignity of the ternary operator.
     
    Mark P, Sep 27, 2007
    #5
  6. bejiz

    Guest

    On Sep 26, 7:33 pm, "Victor Bazarov" <> wrote:
    > Right. I should have added 0.5:
    >
    > int ndigits = x > 0 ? int(log10(x + 0.5)) + 1 : 1;



    Now it won't work for 99.7, 999.7, 9999.7, etc. It's also not clear
    that this does what you want for numbers less than 1.

    I suggest you give this up, you will not be able to make this work
    reliably, since the result of log10() is almost never exact, and you'd
    have to prove that the result is correct around all the powers of 10.
    While you might be able to verify that for any given implementation of
    C++, you can't make the case in general.

    While using the log() operator is likely to be overly expensive in any
    case, you *could* use that to pick an approximation (IOW log10(x)),
    and then test if that needs to be adjusted up or down one, perhaps
    with a table lookup. Something like:


    double powers10[] = {1., 10., 100., 1000., 10000., 100000.,
    1000000....};

    nd = log10(x); //needs range check

    if (x < powers10[nd]) nd--;
    else if (x >=powers10[nd+1) nd++;
     
    , Sep 27, 2007
    #6
  7. bejiz

    James Kanze Guest

    On Sep 27, 7:00 am, ""
    <> wrote:
    > On Sep 26, 7:33 pm, "Victor Bazarov" <> wrote:


    > > Right. I should have added 0.5:


    > > int ndigits = x > 0 ? int(log10(x + 0.5)) + 1 : 1;


    > Now it won't work for 99.7, 999.7, 9999.7, etc. It's also not clear
    > that this does what you want for numbers less than 1.


    It's not clear at all what he wants to begin with; Victor's
    guess is as good as anything else. But if he wants to know how
    many digits are present, the most obvious solution is:

    std::eek:strinstream s ;
    // add whatever format flags are wanted...
    s << value ;
    return s.str().size() ;

    It probably won't be as fast as the solution with log10, but it
    does guarantee that the number you get corresponds exactly to
    the number of characters ostream will generate.

    > I suggest you give this up, you will not be able to make this
    > work reliably, since the result of log10() is almost never
    > exact, and you'd have to prove that the result is correct
    > around all the powers of 10. While you might be able to
    > verify that for any given implementation of C++, you can't
    > make the case in general.


    You could certainly do it for IEEE, at least for numbers in a
    "normal" range. (As for the extremes... what should
    log10(1e300) return? You're not really passing it 1e300 to
    begin with.)

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
     
    James Kanze, Sep 27, 2007
    #7
  8. bejiz

    Guest

    On Sep 27, 5:09 am, James Kanze <> wrote:
    > You could certainly do it for IEEE, at least for numbers in a
    > "normal" range. (As for the extremes... what should
    > log10(1e300) return? You're not really passing it 1e300 to
    > begin with.)



    No, you actually can't. There isn't actually a formal accuracy
    standard for the complex transcendental functions, and the accepted
    "One ULP*" rule (which, IIRC, is suggested by the IEEE standard too))
    leaves enough slack that you can certainly *not* guarantee that all
    implementations will produce identical results. Contract that with
    the basic arithmetic operations, where all operations have an exact
    result in IEEE-754 terms (and mind you that many compilers, even on
    reasonably IEEE compliant hardware, do *not* generate code that
    produces IEEE compliant results, even for basic operations. Consider
    the default operand widening performed/allowed by most x87 code
    generators, so your problem is even worse (and an inappropriately
    lengthened intermediate result may be what's actually passed to the
    log function).


    *Except when that's too hard and it's the "almost always one ULP, two
    in a few cases we can't fix" rule.
     
    , Sep 27, 2007
    #8
  9. wrote:
    > On Sep 26, 7:33 pm, "Victor Bazarov" <> wrote:
    >> Right. I should have added 0.5:
    >>
    >> int ndigits = x > 0 ? int(log10(x + 0.5)) + 1 : 1;

    >
    >
    > Now it won't work for 99.7, 999.7, 9999.7, etc. It's also not clear
    > that this does what you want for numbers less than 1.


    But there is no way to tell how many digits those numbers have! The
    original solution was proposed for the *unsigned* 'x', IOW the one
    that does NOT have a fractional part.

    > I suggest you give this up, [..]


    I suggest you reread the original post and think before you shoot next
    time.

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 27, 2007
    #9
  10. bejiz

    bejiz Guest

    Thanks for your answers. I wanted to know the number of digits so that
    it would be possible to line up the columns of a matrix and choose an
    appropriate size for the spaces. I now think I'll use cout.width() for
    the spaces and the booleans with log10 for guessing the size. I think
    it is possible finding the number of digits of a float by multiplying
    it by a huge power of 10 and then removing the zeros dividing by 10
    until the modulo is different from zero and counting the number of
    digits in the final number.
     
    bejiz, Sep 27, 2007
    #10
  11. bejiz

    Pete Becker Guest

    On 2007-09-27 16:55:08 -0400, bejiz <> said:

    > Thanks for your answers. I wanted to know the number of digits so that
    > it would be possible to line up the columns of a matrix and choose an
    > appropriate size for the spaces. I now think I'll use cout.width() for
    > the spaces and the booleans with log10 for guessing the size. I think
    > it is possible finding the number of digits of a float by multiplying
    > it by a huge power of 10 and then removing the zeros dividing by 10
    > until the modulo is different from zero and counting the number of
    > digits in the final number.


    I suspect you've misunderstood what basic_ostream::width does. It sets
    the width of the field, i.e. the number of characters for each column.
    After you set that, the stream inserter converts the value into text
    and adds as many spaces as are needed to pad the text to the required
    number of characters. You don't, in general, need to guess the size of
    any value.

    --
    Pete
    Roundhouse Consulting, Ltd. (www.versatilecoding.com) Author of "The
    Standard C++ Library Extensions: a Tutorial and Reference
    (www.petebecker.com/tr1book)
     
    Pete Becker, Sep 27, 2007
    #11
  12. bejiz wrote:
    > Thanks for your answers. I wanted to know the number of digits so that
    > it would be possible to line up the columns of a matrix and choose an
    > appropriate size for the spaces. I now think I'll use cout.width() for
    > the spaces and the booleans with log10 for guessing the size. I think
    > it is possible finding the number of digits of a float by multiplying
    > it by a huge power of 10 and then removing the zeros dividing by 10
    > until the modulo is different from zero and counting the number of
    > digits in the final number.


    I think you're overthinking it. The maximum number of significant
    digits in 'float' is 'std::numeric_limits<float>::digits10()', print
    them *all* using 'scientific' notation (%g format in fprintf).

    V
    --
    Please remove capital 'A's when replying by e-mail
    I do not respond to top-posted replies, please don't ask
     
    Victor Bazarov, Sep 27, 2007
    #12
  13. bejiz

    Guest

    On Sep 27, 7:32 am, "Victor Bazarov" <> wrote:
    > > Now it won't work for 99.7, 999.7, 9999.7, etc. It's also not clear
    > > that this does what you want for numbers less than 1.

    >
    > But there is no way to tell how many digits those numbers have! The
    > original solution was proposed for the *unsigned* 'x', IOW the one
    > that does NOT have a fractional part.
    >
    > > I suggest you give this up, [..]

    >
    > I suggest you reread the original post and think before you shoot next
    > time.



    The original poster specified "integer or float." And the question
    was clearly how many digits there were to the left of the decimal
    point, since the OP was wanting to line up the numbers. And the
    "number of digits (to the left of the decimal point)" in the case of
    999.7 is clearly 3.
     
    , Sep 27, 2007
    #13
    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. Marc Schellens

    Number of digits of float value

    Marc Schellens, Apr 21, 2004, in forum: C++
    Replies:
    4
    Views:
    6,782
    Ivan Vecerina
    Apr 21, 2004
  2. mark
    Replies:
    1
    Views:
    543
    Victor Bazarov
    Jun 14, 2004
  3. CHRISTOF WARLICH

    find number of digits

    CHRISTOF WARLICH, Nov 25, 2004, in forum: C++
    Replies:
    13
    Views:
    7,932
    Peter Koch Larsen
    Nov 27, 2004
  4. Chris Rebert
    Replies:
    1
    Views:
    416
    Grant Edwards
    Nov 5, 2010
  5. Tim Chase
    Replies:
    2
    Views:
    599
    Tim Chase
    Nov 6, 2010
Loading...

Share This Page