整数を文字列に変換する方法は?


202

Pythonを使用すると、指定したベースの文字列から整数を簡単に作成できます。

int(str, base). 

私は逆を実行したい:整数から文字列を作成する、つまり次のint2base(num, base)ような関数が欲しい:

int(int2base(x, b), b) == x

関数名/引数の順序は重要ではありません。

任意の数のxベース受け付けます。bint()

これは簡単に記述できる関数です。実際、この質問で説明するよりも簡単です。でも、何かが足りないような気がします。

私は、関数について知りbinocthex、私はいくつかの理由のためにそれらを使用することはできません。

  • これらの関数は、(2.2)との互換性が必要な古いバージョンのPythonでは使用できません

  • 異なる拠点で同じように呼び出すことができる一般的なソリューションが欲しい

  • 2、8、16以外のベースを許可したい

関連した


5
驚くべきことに、任意のビッグベース(1023)で機能するソリューションを提供した人はいませんでした。あなたがそれを必要とする場合は、すべてのベース(INFへの2)のために働く私の解決策をチェックstackoverflow.com/a/28666223/1090562
サルバドール・ダリ

回答:


98

Pythonの古いバージョンとの互換性が必要な場合は、gmpyを使用できます(これには、高速で完全に一般的なintから文字列への変換関数が含まれており、そのような古いバージョン用にビルドできます-以前のリリースを試す必要がある場合があります)最近のものは、由緒あるPythonおよびGMPリリースではテストされていません。少し最近のものだけです。または、速度は遅くなりますが、利便性を高めるために、Pythonコードを使用します。

import string
digs = string.digits + string.ascii_letters


def int2base(x, base):
    if x < 0:
        sign = -1
    elif x == 0:
        return digs[0]
    else:
        sign = 1

    x *= sign
    digits = []

    while x:
        digits.append(digs[int(x % base)])
        x = int(x / base)

    if sign < 0:
        digits.append('-')

    digits.reverse()

    return ''.join(digits)

8
(gmpy2)の場合、アレックスが話すfuncはのようgmpy2.digits(x, base)です。
mlvljr 2012年

2
いくつかのケースでは36を超えるベースが必要なため、掘り出し物が必要であることが私の注意を引きましたdigs = string.digits + string.lowercase + string.uppercase
Paul

4
(またはstring.digits + string.letters
kojiro 2013

3
Pythonにconvert-base-N-to-stringがデフォルトで含まれていない理由は何ですか?(それはJavascriptにあります。)ええ、私たちはすべて独自の実装を書くことができますが、私はこのサイトや他の場所を探し回っていますが、それらの多くにはバグがあります。コアディストリビューションには、テスト済みの信頼できるバージョンが1つ含まれているほうがよいでしょう。
Jason S

4
@ lordscales91 Python 2とx //= base同じよう/=に動作する小数点を使用することもできます。この答えは、それはPythonの2のためだという免責条項を含める必要があります
ヌーメノン

100

驚いたことに、人々は小さなベース(英語のアルファベットの長さよりも小さい)に変換するソリューションのみを提供していました。2から無限大までの任意のベースに変換するソリューションを提供する試みはありませんでした。

だからここに超簡単な解決策があります:

def numberToBase(n, b):
    if n == 0:
        return [0]
    digits = []
    while n:
        digits.append(int(n % b))
        n //= b
    return digits[::-1]

ですから、超巨大な数をベースに変換する必要がある場合577

numberToBase(67854 ** 15 - 102, 577)、あなたに正しい解決策を提供します: [4, 473, 131, 96, 431, 285, 524, 486, 28, 23, 16, 82, 292, 538, 149, 25, 41, 483, 100, 517, 131, 28, 0, 435, 197, 264, 455]

後で好きなベースに変換できます


大学で、20未満の基数を標準表記にフォーマットし、20を超える数を「コロン区切り10進数」にフォーマットする関数を思いつきました。たとえば、int(4545,16)「11c1」と「1:15:45」をint(4545,60)与えた。したがって、関数は3倍の役割を果たしました。10進数、コンピューター風、およびタイムスタンプ形式に変換します。
Peter Raynham

1
この方法の逆関数は何ですか?
Sohrab T

これは、3つの理由で尋ねられた質問には答えません。1:実装ではなく既存のライブラリ関数を求められた質問2:文字列を求められた質問、これはリストを生成します3:これはint(str、ベース)組み込み。
プラグウォッシュ

@plugwash 1)ある時点で、必要な処理を実行するための組み込みライブラリ関数がない場合があるので、独自に作成する必要があります。同意しない場合は、10を底とする数値を577に変換できる組み込み関数を使用して独自のソリューションを投稿してください。2)これは、一部の底の数値の意味が理解されていないためです。3)メソッドのベースがn <= 36に対してのみ機能する理由を少し考えてみることをお勧めします。これを完了すると、関数がリストを返し、その署名が含まれている理由が明らかになります。
サルバドールダリ

1
これは負の数では機能しません。根本的に変更せずに機能させる方法はわかりません。たぶん、1か-1の符号ビットをdigits
wjandrea

89
def baseN(num,b,numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
    return ((num == 0) and numerals[0]) or (baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b])

ref:http : //code.activestate.com/recipes/65212/

これにより、

RuntimeError: maximum recursion depth exceeded in cmp

非常に大きな整数の場合。


5
その簡潔さでエレガント。負でない整数の場合、Python 2.2.3で動作するようです。負の数は無限に再帰します。
Mark Borgerding、2010

+1役立つ; 数字が「0」で始まらない場合の問題を修正
sehe

4
これは静かに失敗します(a)baseが>のlen(numerals)場合、および(b)num % b運により<の場合len(numerals)。たとえば、numerals文字列の長さが36文字しかない場合でも、baseN(60、40)は戻り'1k'、baseN(79、40 )はを発生させIndexErrorます。どちらも何らかのエラーを発生させるはずです。次の場合、エラーを発生させるようにコードを修正する必要がありますnot 2 <= base <= len(numerals)
クリスジョンソン

3
@osa、私のポイントは、書かれたコードが非常に悪い方法で失敗し(静かに、誤解を招く答えを与える)、簡単に修正できるということです。事前に知っていれば間違いはないということなら、blen(numerals)あなたに幸運を超えないでしょう。
Chris Johnson

1
ここでの短絡の使用は、不必要に混乱しているように見えます... ifステートメントだけを使用しないでください...行 return numerals[0] if num == 0 else baseN(num // b, b, numerals).lstrip(numerals[0]) + numerals[num % b]は同じくらい簡単です。
Ian Hincks

83
"{0:b}".format(100) # bin: 1100100
"{0:x}".format(100) # hex: 64
"{0:o}".format(100) # oct: 144

46
しかし、それはそれらの3つのベースだけを行うのですか?
Thomas Ahle、2011年

3
はい、残念ながらカスタムのintベースを指定することはできません。詳細はこちら:docs.python.org/library/string.html#formatstrings
Rost

3
0不要です。Python 2のドキュメントは次のとおり
Evgeni Sergeev

7
あなたは同じ結果を得ることができhex(100)[2:]oct(100)[2:]そしてbin(100)[2:]
Sassan 2016

2
@EvgeniSergeev:2.7 / 3.1以降では不要です。2.6では、明示的な位置(または名前)が必要です。
ShadowRanger 2017

21

すばらしい答えです!私の質問に対する答えは「いいえ」だったと思います。明らかな解決策を見逃していませんでした。これが、回答で表現された優れたアイデアを凝縮するために使用する関数です。

  • 呼び出し元が提供する文字のマッピングを許可(base64エンコードを許可)
  • 負とゼロをチェックします
  • 複素数を文字列のタプルにマッピングします


def int2base(x,b,alphabet='0123456789abcdefghijklmnopqrstuvwxyz'):
    'convert an integer to its string representation in a given base'
    if b<2 or b>len(alphabet):
        if b==64: # assume base64 rather than raise error
            alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
        else:
            raise AssertionError("int2base base out of range")
    if isinstance(x,complex): # return a tuple
        return ( int2base(x.real,b,alphabet) , int2base(x.imag,b,alphabet) )
    if x<=0:
        if x==0:
            return alphabet[0]
        else:
            return  '-' + int2base(-x,b,alphabet)
    # else x is non-negative real
    rets=''
    while x>0:
        x,idx = divmod(x,b)
        rets = alphabet[idx] + rets
    return rets


4
関数のbase64出力を整数に戻すにはどうすればよいですか?
detly

16

再帰的

私が考え簡素化し、ほとんどの投票答えました:

BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(n, b): 
    return "0" if not n else to_base(n//b, b).lstrip("0") + BS[n%b]

RuntimeError: maximum recursion depth exceeded in cmp非常に大きな整数と負の数についても同じアドバイスを使用します。(あなたは使うことができますsys.setrecursionlimit(new_limit)

反復

再帰の問題回避するには

BS="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
def to_base(s, b):
    res = ""
    while s:
        res+=BS[s%b]
        s//= b
    return res[::-1] or "0"

2
美しくリファクタリングされ、ライブラリなし。
Giampaolo Ferradini、

ストップコンディションはreturn BS[0] if not nそれではいけませんか?私のように派手な数字を使用したい場合に備えて:)
Arnaud P

@ArnaudPは同意した。これは私にとってはうまくreturn BS[n] if n < b else to_base(n // b) + BN[n % b]
いき

15

Pythonには、任意の基数で整数を出力するための組み込み関数はありません。必要に応じて、独自に記述する必要があります。


13

baseconv.py私のプロジェクトから使用できます:https : //github.com/semente/python-baseconv

使用例:

>>> from baseconv import BaseConverter
>>> base20 = BaseConverter('0123456789abcdefghij')
>>> base20.encode(1234)
'31e'
>>> base20.decode('31e')
'1234'
>>> base20.encode(-1234)
'-31e'
>>> base20.decode('-31e')
'-1234'
>>> base11 = BaseConverter('0123456789-', sign='$')
>>> base11.encode('$1234')
'$-22'
>>> base11.decode('$-22')
'$1234'

そこたとえばなど、いくつかのbultinコンバータがあるbaseconv.base2baseconv.base16baseconv.base64


12

>>> numpy.base_repr(10, base=3) '101'


素晴らしい解決策。私の場合、clac読み込み時間の問題を回避するためにnumpyを回避していました。numpyをプリロードすると、clacでの単純な式評価の実行時間が3倍以上になります。たとえば clac 1+1 、約40ミリ秒から140ミリ秒になりました。
Mark Borgerding、

1
numpy.base_repr()そのベースとして36の制限があることに注意してください。それ以外の場合は、ValueError
sbdchd

これは、組み込みの「int」関数の制限と一致します。大きな基地では、文字がなくなったときに何をすべきかを決定する必要があります
プラグウォッシュ

4

http://code.activestate.com/recipes/65212/

def base10toN(num,n):
    """Change a  to a base-n number.
    Up to base-36 is supported without special notation."""
    num_rep={10:'a',
         11:'b',
         12:'c',
         13:'d',
         14:'e',
         15:'f',
         16:'g',
         17:'h',
         18:'i',
         19:'j',
         20:'k',
         21:'l',
         22:'m',
         23:'n',
         24:'o',
         25:'p',
         26:'q',
         27:'r',
         28:'s',
         29:'t',
         30:'u',
         31:'v',
         32:'w',
         33:'x',
         34:'y',
         35:'z'}
    new_num_string=''
    current=num
    while current!=0:
        remainder=current%n
        if 36>remainder>9:
            remainder_string=num_rep[remainder]
        elif remainder>=36:
            remainder_string='('+str(remainder)+')'
        else:
            remainder_string=str(remainder)
        new_num_string=remainder_string+new_num_string
        current=current/n
    return new_num_string

これは同じリンクからの別のものです

def baseconvert(n, base):
    """convert positive decimal integer n to equivalent in another base (2-36)"""

    digits = "0123456789abcdefghijklmnopqrstuvwxyz"

    try:
        n = int(n)
        base = int(base)
    except:
        return ""

    if n < 0 or base < 2 or base > 36:
        return ""

    s = ""
    while 1:
        r = n % base
        s = digits[r] + s
        n = n / base
        if n == 0:
            break

    return s

base10toNはNUM == 0の場合を考慮していない
Craeft

3

私はこれのためにpipパッケージを作りました。

bases.js に触発された私のbases.py https://github.com/kamijoutouma/bases.pyを使用することをお勧めします

from bases import Bases
bases = Bases()

bases.toBase16(200)                // => 'c8'
bases.toBase(200, 16)              // => 'c8'
bases.toBase62(99999)              // => 'q0T'
bases.toBase(200, 62)              // => 'q0T'
bases.toAlphabet(300, 'aAbBcC')    // => 'Abba'

bases.fromBase16('c8')               // => 200
bases.fromBase('c8', 16)             // => 200
bases.fromBase62('q0T')              // => 99999
bases.fromBase('q0T', 62)            // => 99999
bases.fromAlphabet('Abba', 'aAbBcC') // => 300

https://github.com/kamijoutouma/bases.py#known-basesalphabetsを参照してください 使用可能なベースを

編集:pipリンクhttps://pypi.python.org/pypi/bases.py/0.2.2


これは、指定された既知の拠点の魅力のように機能します
Agi Hammerthief 2016年

これは断然最良の答えです!そして、pipパッケージをありがとう!
ɹɐʎɯɐʞ

3
def base(decimal ,base) :
    list = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
    other_base = ""
    while decimal != 0 :
        other_base = list[decimal % base] + other_base
        decimal    = decimal / base
    if other_base == "":
        other_base = "0"
    return other_base

print base(31 ,16)

出力:

「1F」


other-baseother - baseother_base
はと

また、decimalがゼロの場合、これは正しく機能しません。
mbomb007 2015

1
>>> import string
>>> def int2base(integer, base):
        if not integer: return '0'
        sign = 1 if integer > 0 else -1
        alphanum = string.digits + string.ascii_lowercase
        nums = alphanum[:base]
        res = ''
        integer *= sign
        while integer:
                integer, mod = divmod(integer, base)
                res += nums[mod]
        return ('' if sign == 1 else '-') + res[::-1]


>>> int2base(-15645, 23)
'-16d5'
>>> int2base(213, 21)
'a3'

1

興味のある人のための再帰的な解決策。もちろん、これは負のバイナリ値では機能しません。Two's Complementを実装する必要があります。

def generateBase36Alphabet():
    return ''.join([str(i) for i in range(10)]+[chr(i+65) for i in range(26)])

def generateAlphabet(base):
    return generateBase36Alphabet()[:base]

def intToStr(n, base, alphabet):
    def toStr(n, base, alphabet):
        return alphabet[n] if n < base else toStr(n//base,base,alphabet) + alphabet[n%base]
    return ('-' if n < 0 else '') + toStr(abs(n), base, alphabet)

print('{} -> {}'.format(-31, intToStr(-31, 16, generateAlphabet(16)))) # -31 -> -1F

1
def int2base(a, base, numerals="0123456789abcdefghijklmnopqrstuvwxyz"):
    baseit = lambda a=a, b=base: (not a) and numerals[0]  or baseit(a-a%b,b*base)+numerals[a%b%(base-1) or (a%b) and (base-1)]
    return baseit()

説明

どのベースでも、すべての数はに等しくなります a1+a2*base**2+a3*base**3...。「ミッション」は、すべてのaを見つけることです。

すべてN=1,2,3...のコードで、 すべてのaがNより大きいスライスaN*base**Nb=base**(N+1)あるbによる「mouduling」によって分離し 、funcがcurrentによって呼び出されるたびに減少することにより、シリアルがNより小さいすべてのaをスライスしますaN*base**N

Base%(base-1)== 1 for base ** p%(base-1)== 1 and forfor q * base ^ p%(base-1)== q for one only exception when q = base-1これは0を返します。0を返す場合に修正するために、funcは最初から0をチェックしています。


利点

このサンプルでは、​​(除算の代わりに)乗算が1つだけあり、比較的時間がかかるいくつかのMouduluesesがあります。


1
num = input("number")
power = 0
num = int(num)
while num > 10:
    num = num / 10
    power += 1

print(str(round(num, 2)) + "^" + str(power))

特別な初期化を行ったという簡単な情報を追加してください
Farhana '15

これは著者の質問に答えるかもしれませんが、説明する単語やドキュメントへのリンクが不足しています。生のコードスニペットは、周りにいくつかのフレーズがないとあまり役に立ちません。また、良い答えの書き方も非常に役立ちます。回答を編集してください。
2018年

1
def base_changer(number,base):
    buff=97+abs(base-10)
    dic={};buff2='';buff3=10
    for i in range(97,buff+1):
        dic[buff3]=chr(i)
        buff3+=1   
    while(number>=base):
        mod=int(number%base)
        number=int(number//base)
        if (mod) in dic.keys():
            buff2+=dic[mod]
            continue
        buff2+=str(mod)
    if (number) in dic.keys():
        buff2+=dic[number]
    else:
        buff2+=str(number)

    return buff2[::-1]   

この関数では、10進数を好きな底に簡単に変換できます。
モンタカミ

あなた自身の答えにコメントする必要はありません、あなたはそれを編集して説明を加えることができます。
ポクムルニク

1

いくつかのベースを別のベースに変換する方法の例を次に示します。

from collections import namedtuple

Test = namedtuple("Test", ["n", "from_base", "to_base", "expected"])


def convert(n: int, from_base: int, to_base: int) -> int:
    digits = []
    while n:
        (n, r) = divmod(n, to_base)
        digits.append(r)    
    return sum(from_base ** i * v for i, v in enumerate(digits))


if __name__ == "__main__":
    tests = [
        Test(32, 16, 10, 50),
        Test(32, 20, 10, 62),
        Test(1010, 2, 10, 10),
        Test(8, 10, 8, 10),
        Test(150, 100, 1000, 150),
        Test(1500, 100, 10, 1050000),
    ]

    for test in tests:
        result = convert(*test[:-1])
        assert result == test.expected, f"{test=}, {result=}"
    print("PASSED!!!")

0
def dec_to_radix(input, to_radix=2, power=None):
    if not isinstance(input, int):
        raise TypeError('Not an integer!')
    elif power is None:
        power = 1

    if input == 0:
        return 0
    else:
        remainder = input % to_radix**power
        digit = str(int(remainder/to_radix**(power-1)))
        return int(str(dec_to_radix(input-remainder, to_radix, power+1)) + digit)

def radix_to_dec(input, from_radix):
    if not isinstance(input, int):
        raise TypeError('Not an integer!')
    return sum(int(digit)*(from_radix**power) for power, digit in enumerate(str(input)[::-1]))

def radix_to_radix(input, from_radix=10, to_radix=2, power=None):
    dec = radix_to_dec(input, from_radix)
    return dec_to_radix(dec, to_radix, power)

0

別の短いもの(そしてimoを理解しやすい):

def int_to_str(n, b, symbols='0123456789abcdefghijklmnopqrstuvwxyz'):
    return (int_to_str(n/b, b, symbols) if n >= b else "") + symbols[n%b]

そして適切な例外処理で:

def int_to_str(n, b, symbols='0123456789abcdefghijklmnopqrstuvwxyz'):
    try:
        return (int_to_str(n/b, b) if n >= b else "") + symbols[n%b]
    except IndexError:
        raise ValueError(
            "The symbols provided are not enough to represent this number in "
            "this base")

0

ベース2から10で機能する別のソリューションは、より高いベースの変更が必要です。

def n2b(n, b):
    if n == 0:
        return 0
    d = []
    while n:
        d.append(int(n % b))
        n /= b
    return ''.join(map(str,d[::-1]))

例:

n2b(10,2) => '10100'
int(n2b(10,2),2) => 10

0

以下は、符号付き整数とカスタム数字を処理する再帰バージョンです。

import string

def base_convert(x, base, digits=None):
    """Convert integer `x` from base 10 to base `base` using `digits` characters as digits.
    If `digits` is omitted, it will use decimal digits + lowercase letters + uppercase letters.
    """
    digits = digits or (string.digits + string.ascii_letters)
    assert 2 <= base <= len(digits), "Unsupported base: {}".format(base)
    if x == 0:
        return digits[0]
    sign = '-' if x < 0 else ''
    x = abs(x)
    first_digits = base_convert(x // base, base, digits).lstrip(digits[0])
    return sign + first_digits + digits[x % base]

0

文字列は、数値を表すための唯一の選択肢ではありません。整数のリストを使用して、各桁の順序を表すことができます。それらは簡単に文字列に変換できます。

どの回答もbase <2を拒否しません。そして、ほとんどが非常に遅く実行されるか、非常に大きな数(56789 ** 43210など)のスタックオーバーフローによりクラッシュします。このような障害を回避するには、次のようにすばやく減らします。

def n_to_base(n, b):
    if b < 2: raise # invalid base
    if abs(n) < b: return [n]
    ret = [y for d in n_to_base(n, b*b) for y in divmod(d, b)]
    return ret[1:] if ret[0] == 0 else ret # remove leading zeros

def base_to_n(v, b):
    h = len(v) // 2
    if h == 0: return v[0]
    return base_to_n(v[:-h], b) * (b**h) + base_to_n(v[-h:], b)

assert ''.join(['0123456789'[x] for x in n_to_base(56789**43210,10)])==str(56789**43210)

スピードワイズは、大きな数値(私のマシンでは約0.3秒)n_to_baseと同等strですが、比較hexすると驚くかもしれません(私のマシンでは約0.3ミリ秒、または1000倍速い)。その理由は、大整数がメモリに256(バイト)で格納されるためです。各バイトは単純に2文字の16進数文字列に変換できます。このアライメントは、2の累乗の基数でのみ発生します。そのため、2、8、16(およびbase64、ascii、utf16、utf32)の特殊なケースがあります。

10進文字列の最後の桁を考慮します。それはその整数を形成するバイトのシーケンスとどのように関係していますか?レッツ・ラベルバイトs[i]s[0]最下位(リトルエンディアン)であること。次に、最後の桁はsum([s[i]*(256**i) % 10 for i in range(n)])です。さて、256 ** iは6 for i> 0(6 * 6 = 36)で終わるため、最後の桁は(s[0]*5 + sum(s)*6)%10です。これから、最後の桁がすべてのバイトの合計に依存していることがわかります。この非ローカルプロパティにより、10進数への変換が困難になります。


0
def baseConverter(x, b):
    s = ""
    d = string.printable.upper()
    while x > 0:
        s += d[x%b]
        x = x / b
    return s[::-1]

python3の場合、コードはこれを実行します:baseConverter(0、26)-> '' baseConverter(1、26)-> '00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000)python2の場合:baseConverter(0、26)->' 'baseConverter(1、26) -> 1 baseConverter(3、26)-> 3 baseConverter(5、26)-> 5 baseConverter(26、26)-> 10 baseConverter(32、26)-> 16
Drachenfels

0

私が書いたこの関数は個人的に使用しています

import string

def to_base(value, base, digits=string.digits+string.ascii_letters):    # converts decimal to base n

    digits_slice = digits[0:base]

    temporary_var = value
    data = [temporary_var]

    while True:
        temporary_var = temporary_var // base
        data.append(temporary_var)
        if temporary_var < base:
            break

    result = ''
    for each_data in data:
        result += digits_slice[each_data % base]
    result = result[::-1]

    return result

これはあなたがそれを使う方法です

print(to_base(7, base=2))

出力: "111"

print(to_base(23, base=3))

出力: "212"

私のコードの改善を遠慮なく提案してください。


0
def base_conversion(num, base):
    digits = []
    while num > 0:
        num, remainder = divmod(num, base)
        digits.append(remainder)
    return digits[::-1]

0

これは古い質問ですが、他の回答よりもいくぶん簡単であると思うので、私の見解を共有したいと思いました(2から36の拠点に適しています)。

def intStr(n,base=10):
    if n < 0   : return "-" + intStr(-n,base)         # handle negatives
    if n < base: return chr([48,55][n>9] + n)         # 48 => "0"..., 65 => "A"...
    return intStr(n//base,base) + intStr(n%base,base) # recurse for multiple digits

-1

ここではフロートのコンバーターを見たことがありません。そして、私は常に3桁のグループ化に失敗しました。

TODO:

(n.nnnnnn*10**(exp)- 科学的表現の数字- '10'self.baseDigits[1::-1]/self.to_string(len (self.baseDigits))

-from_string-function。

-base 1->ローマ数字?

-agleのある複合体のrepr

だからここに私の解決策があります:

DIGITS = "0123456789abcdefghijklmnopqrstuvwxyz"


# note that the order of the digits is reversed for digits before the point
NO_GROUPING = lambda g: g

concat = "".join
concat_backwards = lambda g: concat(e for e in reversed(list(g)))

def grouping(length = 3, char = '_'):
    def yieldor(digits):
        i = 0
        for d in digits:
            if i == length:
                yield char
                i = 0
            yield d
            i+=1

    return yieldor

class Converter:
    def __init__(self, baseDigits: (int, str), beforePoint = NO_GROUPING, afterPoint = NO_GROUPING, decimalPoint = '.', digitPrecision = 16, trimZeros = True):
        if isinstance(baseDigits, int):
            baseDigits = DIGITS[:baseDigits]
        self.baseDigits = baseDigits

        self.beforePoint = beforePoint
        self.afterPoint  = afterPoint

        self.decimalPoint = decimalPoint
        self.digitPrecision = digitPrecision
        self.trimZeros = trimZeros

    def to_string(self, number: (int, float, complex)) -> str:
        if isinstance(number, complex):
            if number.imag == 0:
                return self.to_string(number.real)
            if number.real == 0:
                return self.to_string(number.imag) + 'j'
            return "({}+{}j)".format(self.to_string(number.real), self.to_string (number.imag))
        if number < 0:
            return '-' + self.to_string(-number)
        digitCount = len(self.baseDigits)
        if isinstance(number, float):
            # round correctly
            precError=digitCount**-self.digitPrecision
            number+=0.5*precError
            if self.trimZeros:
                def yieldor(n):
                    p = precError
                    for i in range(self.digitPrecision):
                        if n <= p:
                            return
                        p *= digitCount
                        n *= digitCount
                        digit = int(n)
                        n -= digit
                        yield self.baseDigits[digit]
            else:
                def yieldor(n):
                    for i in range(self.digitPrecision):
                        n *= digitCount
                        digit = int(n)
                        n -= digit
                        yield self.baseDigits[digit]

            a = concat(self.afterPoint(yieldor(number%1)))

            return (
                self.to_string(int(number)) + (a and self.decimalPoint + a)
            )

        else: #is int
            if not number: return self.baseDigits[0]
            def yieldor(n):
                while n:
                    n, digit = divmod(n, digitCount)
                    yield self.baseDigits[digit]
            return concat_backwards(self.beforePoint(yieldor(number)))

# some tests:
if __name__ == "__main__":
    def conv_test(num, digits, *argv, **kwv):
        print(num, "->", digits if isinstance(digits, int) else "{} ({})".format(len(digits), digits), Converter(digits, *argv, **kwv).to_string(num))
    conv_test(True, "ft")
    conv_test(123, 12, grouping(2))
    conv_test(-0xf00d, 16)
    conv_test(1000, True<<True, grouping(4))
    conv_test(1_000_000, "0+-", beforePoint = grouping(2, '|'))
    conv_test(1.5, 10)
    conv_test(0.999999999, 10, digitPrecision = 8)
    conv_test(-0.1, 10)

    import math
    conv_test(math.pi, 10, afterPoint = grouping(5, ' '))
    conv_test(0.123456789, 10, digitPrecision = 6)

    grSpc = grouping(1, ' ')
    conv_test(math.e, ["off", "on"], grSpc, grSpc, " dot ", digitPrecision = 7)

    conv_test(1 + 1.5j, 10)

    conv_test(50j, 10)

    conv_test(10.01, '-<>')

    # and generate some brainfuck-code here:
    conv_test(1701**42, '+-<>,.][', digitPrecision = 32)

-2
def bn(x,b,ab="0123456789abcdefghijklmnopqrstuvwxyz..."
    a = ""
    while (x>0):
        x,r = divmod(x,n)
        a += ab[r]
    return a[::-1]

bn(2**100, 36)

出力:

3ewfdnca0n6ld1ggvfgg

任意のベースに変換するには、逆も簡単です。


もらっNameError: global name 'n' is not definedた あるdivmod(x, n)はずdivmod(x, b)ですか?
wjandrea
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.