Binary String to Decimal String

喜你入骨 提交于 2020-07-04 06:46:36

问题


Good afternoon,

How would you go about converting to a decimal string a binary string with more characters than bits in a language's largest integer type? In other words, supposing that you have the string

111001101001110100100(...)1001001111011100100

and that you can't convert it to an integer first, how would you go about writing it in base 10?

Thank you very much.


回答1:


You can use an algorithm like:

// X is the input
while ( X != "0" )
  compute X' and R such that X = 10 * X' + R  (Euclidean division, see below)
  output R    // least significant decimal digit first
  X = X'

The Euclidean division of X by 10 is computed like this:

R = 0  // remainder in 0..9
X' = ""
for (b in bits of X)  // msb to lsb
  R = 2*R + b
  if R >= 10
    X' += "1"
    R -= 10
  else
    X' += "0"

Remove leading "0" from X'
The remainder is R in 0..9



回答2:


10 is not a power of 2, thus a digit at any place of a binary representation may affect the least significant digit in the decimal representation. You have to store the entire decimal representation to transform the bit string.

If you can't find a long decimal data class / library for your language, you can construct it yourself, it's not hard. Just store enough decimal digits, e.g. as a list, and do the math. You only need addition for this task, so it's extra easy to implement.




回答3:


I'd use an arbitrary precision numeric (bignum) library, like GMP.

GMP has a "gmp_scanf" function that does just what you are asking for.




回答4:


Write your own arithmetic in base 10. Only addition is needed. Example implementation in Python:

from math import log, ceil

def add(a, b):
    """Add b to a in decimal representation."""
    carry = 0
    for i in range(len(b)):
        carry, a[i] = divmod(a[i] + b[i] + carry, 10)
    while carry:
        i += 1
        carry, a[i] = divmod(a[i] + carry, 10)

# an example string
s = bin(3 ** 120)[2:]

# reserve enough decimal digits
res = [0] * int(ceil(len(s) * log(2) / log(10)))

# convert
for c in s:
    add(res, res)
    if c == "1":
        add(res, [1])

#print output
print str.join("", map(str, reversed(res)))

This uses lists of intergers to represent numbers in base 10. The list items correspond to the digits of the base 10 number. The item at index 0 corresponds to the ones, the item at index 1 to the tens, and so on.




回答5:


Assuming that you do not have an arbitrary precision math package at your disposal, but you do have a set of basic string manipulation routines, you could do the following:

Construct a list of powers of 2 then deconstruct the binary string in reverse order one bit at a time by adding in the appropriate power of 2 for every '1' bit in the string.

The only arbitrary precision arithmetic function you need to do this is addition, and this is fairly easy to implement using long-hand arithmetic.

Suppose you did implement an arbitrary arithmetic add function called: ADD taking 2 strings containing decimal numbers as input and returning the decimal sum as a string. Something like:

  SumString = ADD(DecimalString1, DecimalString2)

SumString is a string of decimal digits representing the sum of DecimalString1 and DecimalString2.

Step1: Construct a powers of 2 list as follows:

  BitString is string           /* String of '1' and '0' values... */
  BitString = '111001101001110100100(...)1001001111011100100' /* or whatever... */

  PowerOf2 is array of string  /* Array of strings containing powers of 2 */
  PowerOf2[1] = '1'            /* 2**0 to get things started... */
  /* Build as many powers of 2 as there are 'bits' in the input string */   
  for i from 2 to length(BitString) by +1  
    PowerOf2[i] = ADD(PowerOf2[i-1], PowerOf2[i-1])  
    end 

Note: Above assumes arrays/strings are 1 based (as opposed to zero based).

Step 2: Deconstruct the BitString accumulating the sum as you go:

  DecimalValue is string        /* Decimal value of BitString */
  BitString is string           /* Your input set of bits as a string... */
  ReverseBitString is string    /* Reversed input */

  DecimalValue = ''             /* Result */  
  BitString = '111001101001110100100(...)1001001111011100100' /* or whatever... */  
  ReverseBitString = reverse(BitString) /* Reverse so we process lsb to msb */  

  for i from 1 to length(ReverseBitString) by +1  
     if substr(ReverseBitString, i, 1) == '1' then  /* Bit at position i */  
        DecimalValue = ADD(DecimalValue, PowerOf2[i])  
        end   
     end    

  if DecimalValue = '' then DecimalValue = '0' /* bit string was all zero */   
  Display DecimalValue /* This is the result */  

How to build an arbitrary precision ADD function? It goes something like:

  function ADD (DecVal1 is string, DecVal2 is string) return string  
     SumVal is string   
     Rev1 is string  
     Rev2 is string      
     DigitSum is integer
     CarryDigit is integer

     SumVal = ''               /* Result so far... */
     Rev1 = reverse(DecVal1)   /* Reverse digit order */
     Rev2 = reverse(DecVal2)   /* Reverse digit order */

     /* Pad shorter reversed sting with trailing zeros... */
     if length(Rev1) > length(Rev2) then
        Rev2 = concat(Rev2, copies(length(Rev1) - length(Rev2), '0')
        end
     else
        Rev1 = concat(Rev1, copies(length(Rev2) - length(Rev1), '0')
        end

     /* Sum by digit position, least to most significant */
     CarryDigit = 0    
     for i from 1 to length(Rev1) by + 1
        DigitSum = CtoI(substr(Rev1, i, 1)) + CtoI(substr(Rev2, i, 1)) + CarryDigit
        if DigitSum > 9 then
           DigitSum = DigitSum - 10
           CarryDigit = 1
           end
        else
           CarryDigit = 0
           end 

        SumVal = concat(ItoC(DigitSum), SumVal)
        end

      if CarryDigit > 0 then
        SumVal = concat(ItoC(CarryDigit), SumVal)
        end

      return SumVal  

Assumed built in string functions:

  • reverse(String): Returns the string in reverse order
  • length(String): Returns length of a given string
  • concat(String, String): Returns concatenation of two strings
  • substr(String, start, length): Returns substring of string from start for length characters (1 based)
  • CtoI(String): Returns decimal integer value of given character (eg. '1' = 1, '2' = 2, ...)
  • ItoC(Integer): Returns decimal character representation of integer (eg. 1 = '1', 2 = '2', ...)
  • copies(count, string): Returns count concatinated copies of string


来源:https://stackoverflow.com/questions/5246976/binary-string-to-decimal-string

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!