5

TLDR, at the bottom :)

Brief: I am in a process of creating an basic arithmetic library(addition, subtraction, ...) for handling huge numbers. One of the problem i am facing is printing these huge binary numbers into decimal.

I have huge binary number stored in an array of uint64_t. e.g.

uint64_t a[64] = {0};

Now, the goal is to print the 64*64bits binary number in the console/file as its decimal value.

Initial Work: To elaborate the problem I want to describe how I printed hex value.

int i;
int s = 1;
a[1] = (uint64_t)0xFF;
for(i = s; i>= 0; i--)
{
    printf("0x%08llX, ", a[i]);
}

Output:

0x000000FF, 0x00000000, 

Similarly for printing OCT value I can just take LSB 3 bits from a[64], print decimal equivalent of those bits, 3 bits right shift all the bits of a[64] and keep repeating until all the values of a[64] has been printed. (print in revers order to keep first Oct digit on the right)

I can print Hex and Oct value of a binary of unlimited size just by repeating this unit algorithm, but I could not find/develop one for Decimal which I can repeat over and over again to print a[64](or something bigger).

What I have thought of: My initial idea was to keep subtracting

max_64 =(uint64)10000000000000000000; //(i.e.10^19)

the biggest multiple of 10 inside uint64_t, from a until the value inside a is smaller than max_64 (which is basically equivalent of rem_64 = a%max_64 ) and print the rem_64 value using

printf("%019llu",rem_64);

which is the 1st 19 decimal digits of the number a.

Then do an arithmetic operation similar to (not the code):

a = a/max_64; /* Integer division(no fractional part) to remove right most 19 dec digits from 'a' */

and keep repeating and printing 19 decimal digits. (print in such a way that first found 19 digits are on the right, then next 19 digits on its left and so on...).

The problem is this process is to long and I don't want to use all these to just print the dec value. And was looking for a process which avoids using these huge time consuming arithmetic operations.

What I believe is that there must be a way to print huge size just by repeating an algorithm (similar to how Hex and Oct can be printed) and I hope someone could point me to the right direction.

What my library can do(so far):

  • Add (Using Full-Adder)
  • Sub (Using Full-subtractor)
  • Compare (by comparing array size and comparing array elements)
  • Div (Integer division, no fractional part)
  • Modulus (%)
  • Multiplication (basically adding from several times :( )

I will write code for other operations if needed, but I would like to implement the printing function independent of the library if possible.

Consider the problem like this: You have been given a binary number X of n bits (1<=n<=64*64) you have to print out X in decimal. You can use existing library if absolutely needed but better if unused.

TLDR: Any code, reference or unit algorithm which I can repeat for printing decimal value of a binary of too big and/or unknown size would be much helpful. Emphasis on algorithm i.e. I don't need a code if some one could describe a process I will be able to implement it. Thanks in advance.

asif1268
  • 185
  • 7
  • 3
    Eventually you'll implement division and modulo. Those are what you need to convert to decimal. – user3386109 Apr 23 '19 at 10:30
  • Do you have basic operations implemented (add, sub, div, mod, equal to, greater then, etc.) ? Can you show it? `the biggest multiple of 10 inside uint64_t` What about the "biggest rest of division from uint64_t by the biggest multiple of 10"? Ie. what happens to `a[i] % max_64`? `The problem is this process is to long` - so you did write it? Then please show the code. Maybe proper profiling, rewriting, vectorising the code could be made much faster. – KamilCuk Apr 23 '19 at 10:40
  • @KamilCuk: Updated the question to clarify few of your questions. Unfortunately sharing the code would be a bit complicated so I shared the algorithm. I can clarify why it takes too long, it's because each of the library functions are basically brute force implementation like using Full-Adder to add each bits up to (64*64)bits for adding to these big numbers, same for sub, div, mul...My suggestion would be to consider the problem like this: You have been given a binary number X of n bits (1<=n<=64*64) you have to print out X in decimal without using my library if possible. – asif1268 Apr 23 '19 at 11:55
  • I am doing this operation regardless of the big arithmetics (for starters when the arithmetics is not yet fully functional or tested)... This can be done on 8bit arithmetics alone. simply create hex string (which is easy as you already pointed out) and then convert hex string to dec like in here [How do I convert a very long binary number to decimal?](https://stackoverflow.com/a/33799814/2521214). I think you should read this [Fast bignum square computation](https://stackoverflow.com/q/18465326/2521214) It might interest you a lot ... – Spektre Apr 24 '19 at 07:19

1 Answers1

2

When faced with such doubts, and given that there are many bigint libraries out there, it is interesting to look into their code. I had a look at Java's BigInteger, which has a toString method, and they do two things:

Knuth, Donald, The Art of Computer Programming, Vol. 2, Answers to Exercises (4.4) Question 14.

tucuxi
  • 17,561
  • 2
  • 43
  • 74
  • 1
    Schönhage algorithm is good only for **really big** numbers like `~45000bits` +/- implementation, which is not practical in most cases. So Karatsuba is better option in most cases... – Spektre Apr 24 '19 at 07:16
  • @Spektre Comments in the Java source code find it faster for much [lower thresholds](https://hg.openjdk.java.net/jdk/jdk12/file/06222165c35f/src/java.base/share/classes/java/math/BigInteger.java#l259) Then again, language and compiler optimizations matter, and OP intends to use C and not Java. – tucuxi Apr 24 '19 at 07:44
  • 1
    Yep that was the `+/-implementation` and as JAVA is overally slower than C/C++ the thresholds are lower ... – Spektre Apr 24 '19 at 07:47