Integer Base Function

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Robbie Hatley

    Integer Base Function

    For your enjoyment, a function that expresses any integer with
    absolute value less-than-or-equal-to nine quintillion in any
    base from 2 to 36. (For larger bases, you could expand the
    "digit" character string with, perhaps, foreign letters with
    diacritical marks, if you don't mind iso-8895-1 instead of ASCII.
    And if you don't like the non-std type "long long" you can always
    change it to "long"; but then it could only handle numbers up to
    about 2 billion, instead of 9 quintillion.


    ///////////////////////////////////////////////////////////////////////////
    // //
    // Base //
    // Represent an integer in any base from 2 to 36. //
    // //
    ///////////////////////////////////////////////////////////////////////////

    std::string
    Base
    (
    int base, // must be >= 2 and <= 36
    int precision, // must be >= 1 and <= 63
    long long number, // must be >= -9E18 and <= +9E18
    bool leading_zeros // does user want leading zeros?
    )
    {
    const long long MAX = 922337203685477 5807LL;
    const long long MIN = -922337203685477 5808LL;
    double largest = pow(base, precision) - 1;
    if
    (
    base < 2 || base 36 // If base is out-of-range
    || precision < 1 || precision 63 // or precision is out-of-range
    || number < MIN || number MAX // or number is out-of-range
    || largest MAX // or base/precision combo is out-of-range
    || largest < number // or base/precision combo can't express number
    )
    {
    return std::string("ER ROR"); // then return "ERROR".
    }

    std::ostringstr eam repre;
    if (number < 0)
    {
    number *= (-1);
    repre << '-';
    }

    long long place = 1LL;
    for (int i = 1; i <= precision - 1; ++i)
    {
    place *= base;
    }

    long long value = 0LL;
    std::string digits = "0123456789ABCD EFGHIJKLMNOPQRS TUVWXYZ";
    bool first_non_zero = false;
    for ( ; place 0; place /= base)
    {
    value = number / place;
    if (value 0) first_non_zero = true;
    if (leading_zeros || first_non_zero) repre << digits[value];
    number -= value * place;
    }
    return repre.str();
    }


    --
    Cheers,
    Robbie Hatley
    Tustin, CA, USA
    lonewolfintj at pacbell dot net
    (put "[usenet]" in subject to bypass spam filter)



  • Frederick Gotham

    #2
    Re: Integer Base Function

    Robbie Hatley posted:

    const long long MAX = 922337203685477 5807LL;

    Remove the "LL" tagged on the end, it serves no purpose. In fact, it will
    only hinder you if you decide to change the integer type you're using.
    For info on integer literals, go to page 20 of the following document:




    MAX and MIN are widely used as macro names for other things -- expect
    conflict.


    numeric_limits< long long>::max() would be preferable (unless you need a
    compile-time constant). I haven't checked the Standard, but I'd presume
    that there's a LONGLONG_MAX macro.


    const long long MIN = -922337203685477 5808LL;


    Rather than:

    -922337203685477 5808LL


    I think you need:

    -922337203685477 5807 -1


    (A program is ill-formed if it contains an integer literal which is out
    of range. If you write:

    -922337203685477 5808

    It's intepreted as:

    -(92233720368547 75808)

    And, as you can see, that positive figure is out of range. Therefore you
    need to write:

    -922337203685477 5807 -1


    (But no worries, it's a compile-time constant.)

    double largest = pow(base, precision) - 1;
    if
    (
    base < 2 || base 36 // If base is out-of-range
    || precision < 1 || precision 63 // or precision is
    || out-of-range number < MIN || number MAX // or number
    || is out-of-range largest MAX // or base/precision
    || combo is out-of-range largest < number // or
    || base/precision combo can't express number
    )
    {
    return std::string("ER ROR"); // then return "ERROR".
    }


    I'd consider that inefficient, and would use asserts instead.


    std::ostringstr eam repre;
    if (number < 0)
    {
    number *= (-1);

    You have a bug there.

    The number system used by the machine may have asymmetrical ranges for
    positive and negative integers. There's likely to be a negative value
    which hasn't got a corresponding positive value.

    repre << '-';
    }
    >
    long long place = 1LL;
    for (int i = 1; i <= precision - 1; ++i)
    {
    place *= base;
    }
    >
    long long value = 0LL;
    std::string digits = "0123456789ABCD EFGHIJKLMNOPQRS TUVWXYZ";
    bool first_non_zero = false;
    for ( ; place 0; place /= base)
    {
    value = number / place;
    if (value 0) first_non_zero = true;
    if (leading_zeros || first_non_zero) repre << digits[value];
    number -= value * place;
    }
    return repre.str();
    }

    That's inefficient; there's no need for a "ostringstr eam" object.


    --

    Frederick Gotham

    Comment

    • red floyd

      #3
      Re: Integer Base Function

      Frederick Gotham wrote:
      Robbie Hatley posted:
      >
      >
      > const long long MAX = 922337203685477 5807LL;
      >
      >
      Remove the "LL" tagged on the end, it serves no purpose. In fact, it will
      only hinder you if you decide to change the integer type you're using.
      For info on integer literals, go to page 20 of the following document:
      >

      >
      >
      MAX and MIN are widely used as macro names for other things -- expect
      conflict.
      >
      >
      numeric_limits< long long>::max() would be preferable (unless you need a
      compile-time constant). I haven't checked the Standard, but I'd presume
      that there's a LONGLONG_MAX macro.
      >
      >
      I don't believe that long long is in the Standard yet (ISO/IEC
      14882:2003). I think it's included in the draft C++0x for C99
      compatibility.

      Comment

      • Jack Klein

        #4
        Re: Integer Base Function

        On Sun, 02 Jul 2006 17:54:31 GMT, red floyd <no.spam@here.d udewrote
        in comp.lang.c++:
        Frederick Gotham wrote:
        Robbie Hatley posted:

        const long long MAX = 922337203685477 5807LL;

        Remove the "LL" tagged on the end, it serves no purpose. In fact, it will
        only hinder you if you decide to change the integer type you're using.
        For info on integer literals, go to page 20 of the following document:




        MAX and MIN are widely used as macro names for other things -- expect
        conflict.


        numeric_limits< long long>::max() would be preferable (unless you need a
        compile-time constant). I haven't checked the Standard, but I'd presume
        that there's a LONGLONG_MAX macro.
        >
        I don't believe that long long is in the Standard yet (ISO/IEC
        14882:2003). I think it's included in the draft C++0x for C99
        compatibility.
        ....and for absolute necessity. It is very handicapping for a language
        not to have an integer type that can contain the size of any file in
        the file system, for example. Or, on a busy day, the number of shares
        traded on the New York and NASDAQ stock exchanges together will
        overflow a signed 32-bit value. I think, but can't be bothered to
        look up, the fact that the NASDAQ volume alone has exceeded 0x7fffffff
        shares on a few days.

        --
        Jack Klein
        Home: http://JK-Technology.Com
        FAQs for
        comp.lang.c http://c-faq.com/
        comp.lang.c++ http://www.parashift.com/c++-faq-lite/
        alt.comp.lang.l earn.c-c++

        Comment

        • Pete Becker

          #5
          Re: Integer Base Function

          Jack Klein wrote:
          On Sun, 02 Jul 2006 17:54:31 GMT, red floyd <no.spam@here.d udewrote
          in comp.lang.c++:
          >
          >>Frederick Gotham wrote:
          >>
          >>
          >>I don't believe that long long is in the Standard yet (ISO/IEC
          >>14882:2003) . I think it's included in the draft C++0x for C99
          >>compatibility .
          >
          >
          ...and for absolute necessity. It is very handicapping for a language
          not to have an integer type that can contain the size of any file in
          the file system, for example.
          C++ already has such a type. Its name can be int, or more likely, long.
          The problem is compilers that don't take advantage of the flexibility of
          the C and C++ integral types, for various reasons, both good and bad.

          Comment

          • Robbie Hatley

            #6
            Re: Integer Base Function

            "Frederick Gotham" <fgothamNO@SPAM .comwrote of my Base
            function:
            Robbie Hatley posted:
            const long long MAX = 922337203685477 5807LL;
            Remove the "LL" tagged on the end, it serves no purpose.
            Like many other things I do in my code, its purpose has
            has more to do with reminding human readers (including myself)
            of various things, than satisfying linguistic or computational
            requirements.
            In fact, it will only hinder you if you decide to change
            the integer type you're using.
            Like, to "long long long"? :-) If, some day, we get 128bit
            integers available.

            long long long Ago;
            In_A_Galaxy(Far Far Away);

            (Or maybe "infinitely_lon g int", a type that stretches; it's
            however big it needs to be. If you assign a number to it
            that has more digits than its memory can handle, your program
            just allocates more memory. Now why hasn't anyone thunk of
            that yet? If std::string can do it, why not have an integer
            type that can, too? )
            For info on integer literals, go to page 20 of the following document:
            http://www.open-std.org/jtc1/sc22/wg...2005/n1905.pdf
            879 pages? Wow, that's enormous. I can see the stds. committee
            have been busy. Thanx for the reference. I saved a copy. I agree,
            the new wording on page 20 is less confusing than the struck-out
            version.
            MAX and MIN are widely used as macro names for other things -- expect
            conflict.
            Good point. "Max" and "Min" would be better.
            numeric_limits< long long>::max() would be preferable
            Very good point. Esp. if I were to templatize the function.
            Then I could do:

            template<typena me T>
            std::string Base(int base, int precision, T number)
            {
            T Max = numeric_limits< T>::max() - 5; // see below
            T Min = numeric_limits< T>::min() + 5; // see below
            // etc.
            }
            If you write:
            >
            -922337203685477 5808
            >
            It's intepreted as:
            >
            -(92233720368547 75808)
            Hmmm... yes, I see in section 2.13.1 that you're right.
            Therefore you need to write:
            -922337203685477 5807 -1
            I'll either use -922337203685477 5803 or numerical_limit <T>::min().
            if (any of several error conditions are true)
            {
            return std::string("ER ROR"); // then return "ERROR".
            }
            >
            I'd consider that inefficient, and would use asserts instead.
            assert() calls abort(), which crashes the calling application
            and dumps big ugly core all over the user's screen. Not necessary
            just because a display function such as this fails. Better is
            to just return an error message which the caller can display,
            react-to, or ignore. Even throwing an exception would be
            overkill in this case, I think, because that would force callers
            to catch() them; else, again, abort() is called.

            (Though, now that I think of it, "ERROR" is a very bad choice,
            because in bases over 26, it's a valid number!)
            std::ostringstr eam repre;
            if (number < 0)
            {
            number *= (-1);
            >
            You have a bug there.
            >
            The number system used by the machine may have asymmetrical ranges for
            positive and negative integers. There's likely to be a negative value
            which hasn't got a corresponding positive value.
            Usually, 2's compliment is used for signed numbers, in which case
            TYPE_MIN = -(TYPE_MAX + 1), so all positive integers are invertible.
            (TYPE_MIN, on the other hand, is always the one integer that's NOT
            invertible in 2's compliment.)

            However, I see upon looking at section 3.9.1 parargraph 2 that the
            std. doesn't really specify the number system for signed integers.
            So maybe this will do the trick, unless the system is VERY
            asymmetrical:

            T Max = numeric_limits< T>::max() - 5;
            T Min = numeric_limits< T>::min() + 5;
            if (condition) repre << digits[value];
            >
            That's inefficient; there's no need for a "ostringstr eam" object.
            Since the stuff I'm writing to the stringstream are just characters,
            I suppose I could make repre a std::string and do:

            if (condition) repre += digits[value];

            Yes, that would be more efficient.

            Thanks for the tips.

            --
            Cheers,
            Robbie Hatley
            Tustin, CA, USA
            lonewolfintj at pacbell dot net
            (put "[usenet]" in subject to bypass spam filter)



            Comment

            • Robbie Hatley

              #7
              Re: Integer Base Function

              "Pete Becker" <petebecker@acm .orgwrote:
              Jack Klein wrote:
              red floyd wrote:
              Frederick Gotham wrote:
              >
              I don't believe that long long is in the Standard yet (ISO/IEC
              14882:2003). I think it's included in the draft C++0x for C99
              compatibility.
              and for absolute necessity. It is very handicapping for a language
              not to have an integer type that can contain the size of any file in
              the file system, for example.
              >
              C++ already has such a type. Its name can be int, or more likely, long.
              The problem is compilers that don't take advantage of the flexibility of
              the C and C++ integral types, for various reasons, both good and bad.
              My friend Ron, a firmware developer, abhors the C / C++ "int", "short",
              "long" types. He never uses them directly. He says, "What's 'long'?
              Exactly how 'long' is it, in bits? 32, you say? Who's #$^*@! opinion
              is it that that constitutes 'long'? AARRGG!!!"

              Instead, he uses int8, uint8, int16, uint16, etc, all typedefed to
              "char", "short", etc. for the particular platform & compiler he's
              working with.

              I think the C and C++ standards should both define the following types
              as absolutely mandatory basic integer types (actual keywords, not just
              typedefs):

              int8
              uint8
              int16
              uint16
              int32
              uint32
              int64
              uint64

              Firmware folks would love that, since they often need to control
              EXACTLY how many bits they're using. (When your CPU only has
              512 bytes of RAM, every bit counts.) And their code would become
              more portable, because they'd know that a uint16 on one system
              will always be exactly the same as a uint16 on another. (Which
              isn't true of short, long, etc.)

              --
              Cheers,
              Robbie Hatley
              Tustin, CA, USA
              lonewolfintj at pacbell dot net
              (put "[usenet]" in subject to bypass spam filter)



              Comment

              • Frederick Gotham

                #8
                Re: Integer Base Function

                Robbie Hatley posted:

                >In fact, it will only hinder you if you decide to change
                >the integer type you're using.
                >
                Like, to "long long long"? :-) If, some day, we get 128bit
                integers available.

                It would be nice to be able to change effortlessly to any other integer
                type, be it unsigned int, unsigned short, unsigned long, unsigned char...

                Good point. "Max" and "Min" would be better.

                I use all lowercase for object names, but you have your coding style and
                I have mine.

                >I'd consider that inefficient, and would use asserts instead.
                >
                assert() calls abort(), which crashes the calling application
                and dumps big ugly core all over the user's screen. Not necessary
                just because a display function such as this fails. Better is
                to just return an error message which the caller can display,
                react-to, or ignore. Even throwing an exception would be
                overkill in this case, I think, because that would force callers
                to catch() them; else, again, abort() is called.

                The asserts would be used for debugging only. The idea I had in mind is
                that you make sure the figures are correct BEFORE calling the function.

                I like to keep my code as efficient as possible, and so I keep all the
                input-checking and error-checking code in one place.

                >The number system used by the machine may have asymmetrical ranges for
                >positive and negative integers. There's likely to be a negative value
                >which hasn't got a corresponding positive value.
                >
                Usually, 2's compliment is used for signed numbers, in which case
                TYPE_MIN = -(TYPE_MAX + 1), so all positive integers are invertible.
                (TYPE_MIN, on the other hand, is always the one integer that's NOT
                invertible in 2's compliment.)

                Yes, but not all negative numbers can be negated (which is exactly what
                your code does).

                Anyway, the canonical way to negate a number is:

                x = -x;

                rather than:

                x *= -1;

                However, I see upon looking at section 3.9.1 parargraph 2 that the
                std. doesn't really specify the number system for signed integers.

                It does somewhere in there. The system must either be:

                Two's complement
                One's complement
                Sign-magnitude


                >That's inefficient; there's no need for a "ostringstr eam" object.
                >
                Since the stuff I'm writing to the stringstream are just characters,
                I suppose I could make repre a std::string and do:
                >
                if (condition) repre += digits[value];
                >
                Yes, that would be more efficient.

                I myself would use a raw char buffer... but then again I'm a "C++
                programmer with a heavy bias towards C".

                Thanks for the tips.

                You're welcome.


                --

                Frederick Gotham

                Comment

                • Frederick Gotham

                  #9
                  Re: Integer Base Function

                  Robbie Hatley posted:

                  int8
                  uint8
                  int16
                  uint16
                  int32
                  uint32
                  int64
                  uint64

                  Rather than specifying how many value representation bits an integer type
                  has, these typedef's would have to specify the minimum amount they have,
                  because some systems have 9-Bit bytes and 36-Bit int's. Also, an integer
                  may contain padding bits (except for the char family).



                  --

                  Frederick Gotham

                  Comment

                  • Robbie Hatley

                    #10
                    Re: Integer Base Function

                    "Frederick Gotham" wrote:
                    Robbie Hatley posted:
                    >
                    int8
                    uint8
                    int16
                    uint16
                    int32
                    uint32
                    int64
                    uint64
                    >
                    >
                    Rather than specifying how many value representation bits an integer type
                    has, these typedef's would have to specify the minimum amount they have,
                    because some systems have 9-Bit bytes and 36-Bit int's. Also, an integer
                    may contain padding bits (except for the char family).
                    Actually, that's a bit of a misquote. What I said was:
                    I think the C and C++ standards should both define the
                    following types as ABSOLUTELY MANDATORY BASIC INTEGER TYPES
                    (ACTUAL KEYWORDS, NOT JUST TYPEDEFS):
                    >
                    int8
                    uint8
                    int16
                    uint16
                    int32
                    uint32
                    int64
                    uint64
                    Perhaps you're right, though, in that some system archetectures
                    may make impliementing these difficult or impossible. Perhaps
                    they should be optional typedefs, as you say, instead of
                    mandatory basic types, as had been my idea.

                    Note that the current C standard (C99) has already has optional
                    exact-integer-length typedefs int8_t, uint8_t, int16_t, etc..

                    Also, the C std. has these NON-optional (ie, mandatory) types,
                    listed in C99 section 7.18.1.1 paragraph 3:

                    The following types are required:
                    int_least8_t
                    int_least16_t
                    int_least32_t
                    int_least64_t
                    uint_least8_t
                    uint_least16_t
                    uint_least32_t
                    uint_least64_t

                    These are the ones that function like the minimum-length typedefs
                    you described.

                    The C++ standard doesn't have these, though. And surprisingly,
                    I see no sign of these in the working draft, either. A shame.
                    I think C++ should include all of the above, both the optional
                    exact-length "intN_t" typedefs (int16_t or int27_t or whatever),
                    and the eight mandatory "minimum size" typedefs.


                    --
                    Cheers,
                    Robbie Hatley
                    Tustin, CA, USA
                    lonewolfintj at pacbell dot net
                    (put "[usenet]" in subject to bypass spam filter)



                    Comment

                    • Jerry Coffin

                      #11
                      Re: Integer Base Function

                      In article <O3jqg.59849$Lm 5.50114@newssvr 12.news.prodigy .com>,
                      bogus.address@n o.spam says...

                      [ stuff in C99's stdint.h ]
                      The C++ standard doesn't have these, though. And surprisingly,
                      I see no sign of these in the working draft, either. A shame.
                      I think C++ should include all of the above, both the optional
                      exact-length "intN_t" typedefs (int16_t or int27_t or whatever),
                      and the eight mandatory "minimum size" typedefs.
                      These are in TR1, so even if the editing hasn't been done to put them
                      into the new C++ standard, it seems likely that it's more a matter of
                      administrivia than any likelihood they'll be excluded.

                      --
                      Later,
                      Jerry.

                      The universe is a figment of its own imagination.

                      Comment

                      • Robbie Hatley

                        #12
                        Re: Integer Base Function

                        "Frederick Gotham" wrote:
                        I myself would use a raw char buffer
                        I think I'll go for just a char array for my "digits" string,
                        because it's a small container of 36 chars which never change:

                        // overkill:
                        std::string digits = "0123456789ABCD EFGHIJKLMNOPQRS TUVWXYZ";

                        // more efficient:
                        const char digits[37] = "0123456789ABCD EFGHIJKLMNOPQRS TUVWXYZ";

                        But for the return value, I prefer to return a std::string object
                        by value. That way, the calling function gets its own independent
                        copy of the results.
                        but then again I'm a "C++ programmer with a heavy bias towards C".
                        I, too, find myself biased towards some C-style C++ programming
                        paradigms (such as, I often tend to think procedurally when
                        perhaps I should be thinking in terms of OOP). This is, perhaps,
                        due to my past background in other languages (APL, Fortran, Basic).

                        But there are certain features of C++ which I love so much that
                        I rarely use C anymore, except for firmware or tiny utility apps:

                        namespaces
                        std containers
                        std::string
                        std algorithms
                        std iterators
                        parameterized constructors
                        templates
                        functors

                        I had a dream a while back in which the C++ standards committee
                        had decided to remove all those from the language. When I woke
                        up and realized it was just a nightmare, I was very relieved!

                        For comparison, consider two programmers' implimentations of a
                        list of strings:

                        My friend Ron, in C:

                        (snip 500 lines of tricky code)

                        Me, in C++:

                        std::list<std:: stringMyNiceLis tOfStrings;

                        ::gloat:: ::gloat::


                        --
                        Cheers,
                        Robbie Hatley
                        Tustin, CA, USA
                        lonewolfintj at pacbell dot net
                        (put "[usenet]" in subject to bypass spam filter)



                        Comment

                        • Pete Becker

                          #13
                          Re: Integer Base Function

                          Robbie Hatley wrote:
                          >
                          Also, the C std. has these NON-optional (ie, mandatory) types,
                          listed in C99 section 7.18.1.1 paragraph 3:
                          >
                          The following types are required:
                          int_least8_t
                          int_least16_t
                          int_least32_t
                          int_least64_t
                          uint_least8_t
                          uint_least16_t
                          uint_least32_t
                          uint_least64_t
                          >
                          These are the ones that function like the minimum-length typedefs
                          you described.
                          >
                          The C++ standard doesn't have these, though. And surprisingly,
                          I see no sign of these in the working draft, either.
                          >
                          Page 404, N2009.pdf.

                          Comment

                          • Earl Purple

                            #14
                            Re: Integer Base Function


                            Robbie Hatley wrote:
                            But there are certain features of C++ which I love so much that
                            I rarely use C anymore, except for firmware or tiny utility apps:
                            >
                            namespaces
                            std containers
                            std::string
                            std algorithms
                            std iterators
                            parameterized constructors
                            templates
                            functors
                            so if you like templates so much, and since your code is all inlined
                            anyway, why not make the function a template on its integral type?

                            You can use numeric_limits to find out some of the information you need
                            about what type you have.

                            Comment

                            • Robbie Hatley

                              #15
                              Re: Integer Base Function

                              I'd said:
                              The C++ standard doesn't have [exact-size and minimum-size
                              integers], though. And surprisingly, I see no sign of these
                              in the working draft, either.
                              And Pete Becker replied:
                              Page 404, N2009.pdf.
                              Thanks. I was looking at a copy of the working draft from
                              last October (N1905). Obviously lots has changed since then.
                              I just grabbed a copy of N2009.pdf from open-stds.org for my
                              own reference.

                              I see you're the author of that document. At least you're up front
                              about the fact that some of the things in it are "incomplet and
                              incorrekt and contain bad formatting". :-) Looks pretty
                              clean to me, in spite of that. Thanks for all the hard work
                              improving the language.


                              --
                              Cheers,
                              Robbie Hatley
                              Tustin, CA, USA
                              lonewolfintj at pacbell dot net
                              (put "[usenet]" in subject to bypass spam filter)



                              Comment

                              Working...