7

If I have some base 10 or base 16 number, how do I change it into base 232?

The reason I'm trying to do this, is for implementing BigInt as suggested by other members here Why to use higher base for implementing BigInt?

Will it be the same as integer (base 10) till 232? What will happen after it?

phuclv
  • 37,963
  • 15
  • 156
  • 475
questions
  • 2,337
  • 4
  • 24
  • 39
  • 1
    Ummmm....is an `int` a 32 bit int on your system? –  Apr 16 '12 at 19:30
  • 4
    Base 2^32 is incredibly huge. I don't think it's what you want. – Richard J. Ross III Apr 16 '12 at 19:30
  • Yes, I need base 2^32 for implementing BigInt as suggested in the previous question I asked. – questions Apr 16 '12 at 19:31
  • 8
    @questions: No, you don't. I don't think you understand what a Base N number system is, otherwise you would not be asking for base 2^32. – Ed S. Apr 16 '12 at 19:31
  • 5
    Are you the guy also asking about BigIntegers? If so, base 2^32 should mean that the main unit in your design is 32bit integers. You represent a base 2^32 integer as each digit being a 32bit int. You basically make a linked list of ints. – Spidey Apr 16 '12 at 19:33
  • @Spidey- yes, I'm the same guy.. Can you please throw some light on that.. – questions Apr 16 '12 at 19:34
  • 10
    @EdS.: "Base N" means that a number is represented by a sequence of smaller numbers, each in the range `[0,N)`. So base 2^32 makes perfect sense: it means that large numbers are represented by a sequence of 32-bit numbers. – Mike Seymour Apr 16 '12 at 19:42
  • 1
    @MikeSeymour: I know what Base N means and no, it does not make "perfect sense" (at least, to me) if you read the question. The OP doesn't need a new number system, he needs large integer types. He doesn't need a single digit to be able to represent any number between 0 and 4294967295, he needs to use a combination of values (represented in Base 2 in the computer) to represent a numerical value with a larger range than a 32-bit value would allow for. – Ed S. Apr 16 '12 at 19:48
  • 4
    @EdS.: What you are describing is a base-2^32 system. The OP wishes to convert a base-10 representation into something of the form `a0 + a1*(2^32) + a2*(2^32)^2 + ...`, so he needs a base-10-to-base-2^32 converter. We happen to call that a "big integer" data-type, but that doesn't invalidate the OP's question. – Oliver Charlesworth Apr 16 '12 at 19:50
  • 4
    @EdS.: Indeed; a "combination of (32-bit) values to represent a numerical value with a larger range than a 32-bit value" is exactly what a base-2^32 representation of a large number is, and exactly what the OP wants. Why do you say that that isn't a base-2^32 representation? – Mike Seymour Apr 16 '12 at 19:52
  • @MikeSeymour: Ok, I see what you are saying now, I was just confused by the way the question was worded. – Ed S. Apr 16 '12 at 19:52

5 Answers5

12

You are trying to find something of the form

a0 + a1 * (2^32) + a2 * (2^32)^2 + a3 * (2^32)^3 + ...

which is exactly the definition of a base-232 system, so ignore all the people that told you that your question doesn't make sense!

Anyway, what you are describing is known as base conversion. There are quick ways and there are easy ways to solve this. The quick ways are very complicated (there are entire chapters of books dedicated to the subject), and I'm not going to attempt to address them here (not least because I've never attempted to use them).

One easy way is to first implement two functions in your number system, multiplication and addition. (i.e. implement BigInt add(BigInt a, BigInt b) and BigInt mul(BigInt a, BigInt b)). Once you've solved that, you will notice that a base-10 number can be expressed as:

b0 + b1 * 10 + b2 * 10^2 + b3 * 10^3 + ...

which can also be written as:

b0 + 10 * (b1 + 10 * (b2 + 10 * (b3 + ...

so if you move left-to-right in your input string, you can peel off one base-10 digit at a time, and use your add and mul functions to accumulate into your BigInt:

BigInt a = 0;
for each digit b {
    a = add(mul(a, 10), b);
}

Disclaimer: This method is not computationally efficient, but it will at least get you started.

Note: Converting from base-16 is much simpler, because 232 is an exact multiple of 16. So the conversion basically comes down to concatenating bits.

Oliver Charlesworth
  • 267,707
  • 33
  • 569
  • 680
  • 2
    +1 The downvote is bizarre. Lots of up-votes for the answers that miss the target though! But it does seem that the question is ripe for mis-understanding which I guess is why there are downvotes for good answers. – David Heffernan Apr 16 '12 at 20:10
  • @OliverCharlesworth, could you give any advice on how to convert more efficiently? Because I've tried this method and it is too slow for me. (sorry for necroposting) – Akiiino Mar 27 '16 at 11:08
  • @Akiiino - As I hinted in my original answer, there *are* more efficient methods, but I only know of their existence, I don't know the details! – Oliver Charlesworth Mar 27 '16 at 12:07
5

Let's suppose that we are talking about a base-10 number:

a[0]*10^0 + a[1]*10^1 + a[2]*10^2 + a[3]*10^3 + ... + a[N]*10^N

where each a[i] is a digit in the range 0 to 9 inclusive.

I'm going to assume that you can parse the string that is your input value and find the array a[]. Once you can do that, and assuming that you have already implemented your BigInt class with the + and * operators, then you are home. You can simply evaluate the expression above with an instance of your BigInt class.

You can evaluate this expression relatively efficiently using Horner's method.

I've just written this down off the top of my head, and I will bet that there are much more efficient base conversion schemes.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
4

If I have some base 10 or base 16 number, how do I change it into base 2^32?

Just like you convert it to any other base. You want to write the number n as

n = a_0 + a_1 * 2^32 + a_2 * 2^64 + a_3 * 2^96 + ... + a_k * 2^(32 * k).

So, find the largest power of 2^32 that divides into n, subtract off the multiple of that power from n, and repeat with the difference.

However, are you sure that you asked the right question?

I suspect that you mean to be asking a different question. I suspect that you mean to ask: how do I parse a base-10 number into an instance of my BigInteger? That's easy. Code up your implementation, and make sure that you've implemented + and *. I'm completely agnostic to how you actually internally represent integers, but if you want to use base 2^32, fine, do it. Then:

 BigInteger Parse(string s) {
      BigInteger b = new BigInteger(0);
      foreach(char c in s) { b = b * 10 + (int)c - (int)'0'; }
      return b;
 } 

I'll leave it to you to translate this to C.

jason
  • 236,483
  • 35
  • 423
  • 525
  • 1
    How do you do log(n) when `n` doesn't fit into a register?! – David Heffernan Apr 16 '12 at 19:45
  • "How do you do log(n) when n doesn't fit into a register?!" You change your internal representation of `n` -- in base 2^32. – 000 Apr 16 '12 at 19:48
  • 2
    @joeframbach Chicken, meet egg; egg, meet chicken – David Heffernan Apr 16 '12 at 19:50
  • Also, how do you get `n` into the system when it comes in a 2000 character string? This answer relies on the existence of the facility that the question is asking for. In order to implement the code in this answer, you first need to convert the long base-10 string into a `BigInt`! – David Heffernan Apr 16 '12 at 19:53
  • 1
    +1 for being the only answer so far that understands why the OP is asking this question. However, -1 for not really solving the problem, so netting out at 0. – Oliver Charlesworth Apr 16 '12 at 19:54
  • @David Heffernan: There's no code in my answer. And actually implementing a solution to this doesn't rely on what you say it does at all. There's no chicken and egg here. Implement your `BigInteger` class. I'm agnostic to what representation you use. Implement `*` and `+` on this class. Now you want to parse `12312398712309417234123412312037`. Well, just do this: `BigInteger b = new BigInteger(0); foreach(char c in s) { b = b * 10 + (int)(c - '0'); }` return b;. Like I said in my answer: "However, are you sure that you asked the right question?" – jason Apr 16 '12 at 20:06
  • The algorithm you describe in that comment is that found in my answer and Oli's. However, in your answer you don't say that. Instead you suggest starting with `k = floor(log(n) / (32 * log(2)))` but I don't see where `n` comes from, or indeed `log` on a big int. – David Heffernan Apr 16 '12 at 20:08
1

Base 16 is easy, since 232 is 168, an exact power. So, starting from the least significant digit, read 8 base-16 digits at a time, convert those digits into a 32-bit value, and that is the next base-232 "digit".

Base 10 is more difficult. As you say, if it's less than 232, then you just take the value as a single base-232 "digit". Otherwise, the simplest method I can think of is to use the Long Division algorithm to repeatedly divide the base-10 value by 232; at each stage, the remainder is the next base-232 "digit". Perhaps someone who knows more number theory than me could provide a better solution.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0

I think this is a totally reasonable thing to do.

What you are doing is representing a very large number (like an encryption key) in an array of 32 bit integers.

A base 16 representation is base 2^4, or a series of 4 bits at a time. If you are receiving a stream of base 16 "digits", fill in the low 4 bits of the first integer in your array, then the next lowest, until you read 8 "digits". Then go to the next element in the array.

long getBase16()
{
  char cCurr;

  switch (cCurr = getchar())
  {
  case 'A':
  case 'a':
    return 10;
  case 'B':
  case 'b':
    return 11;
  ...
  default:
    return cCurr - '0';
  }
}

void read_input(long * plBuffer)
{
  long * plDst = plBuffer;
  int iPos = 32;

  *(++plDst) = 0x00;

  long lDigit;
  while (lDigit = getBase16())
  {
     if (!iPos)
     {
       *(++plDst) = 0x00;
       iPos = 32;
     }

     *plDst >> 4;
     iPos -= 4;
     *plDst |= (lDigit & 0x0F) << 28
  }
}

There is some fix up to do, like ending by shifting *plDst by iPos, and keeping track of the number of integers in your array.

There is also some work to convert from base 10.

But this is enough to get you started.

Marlin Pierce
  • 9,931
  • 4
  • 30
  • 52