Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How does std::cout convert numerical types to base 10?

I've learned that numerical types, such as int and long long, are stored in a base-two format in C++. These individual bits can be accessed and modified using bitwise operators.

However, I recently wondered why numbers weren't printed to the screen from std::cout in base 2 as well, and thought that they must've been converted to base 10 before being printed. In other words, since std::cout outputs these numbers in base 10, I think that there must be some conversion process going on to convert these numbers from base-2 to base-10.

Overall, my question is, does std::cout actually convert numbers from base 2 to base 10, and how does it do so? Am I making some other logical mistake here?

like image 595
Anthony Smith Avatar asked Nov 17 '20 17:11

Anthony Smith


1 Answers

I find the libstdc++ (gcc's standard library) source almost unnavigable, but I think the meat of it is done here:

https://github.com/gcc-mirror/gcc/blob/8e8f6434760cfe2a1c6c9644181189fdb4d987bb/libstdc%2B%2B-v3/include/bits/locale_facets.tcc#L794

Which appears to use the good ol' "divide by 10 and print remainder" technique for decimal digits:

do
  {
    *--__buf = __lit[(__v % 10) + __num_base::_S_odigits];
    __v /= 10;
  }
while (__v != 0);

To break this down a bit, remember that the char type is just a number, and when you write a char, it looks the character up in a table. In both the old ASCII and newer UTF-8 character encodings, '0' is 48, '1' is 49, '2' is 50, etc. This is extremely convenient because you can print any digit 0-9 by adding it to '0':

putchar('0' + 3) // prints 3

So, to get each digit, divide by 10 and the remainder is the last digit:

int x = 123;
putchar('0' + (x % 10)) // prints '0' + 3, or '3'
x = x / 10;             // x = 12
putchar('0' + (x % 10)) // prints '0' + 2, or '2'
x = x / 10;             // x = 1
putchar('0' + (x % 10)) // prints '0' + 1, or '1'
x = x / 10;             // x = 0, stop

The snippet from the library is just doing that in a loop.

You'll notice the code prints the digits backwards. That's why the snippet from the library decrements the character pointer each iterator (*--__buf = ...) - it's starting at the right and printing it in reverse right-to-left.

like image 185
parktomatomi Avatar answered Sep 28 '22 03:09

parktomatomi