2 Stimmen

Basisumrechnung für ein Array von Ganzzahlen

Ich versuche, einen Code zu erstellen, der Ganzzahlen in einem Array in eine gegebene Basis umwandelt und sie auffüllt, um sie auf die gleiche Größe zu bringen. Der folgende Code, den ich von einem Code auf stackoverflow von Alex Martelli manipuliert habe, funktioniert nicht, wenn ich numpy.vectorize darauf anwende, obwohl es für einzelne Arrays funktioniert:

def int2base(x, base,size):
    ret=np.zeros(size)
    if x==0: return ret
    digits = []
    while x:
        digits.append(x % base)
        x /= base
    digits.reverse()
    ret[size-len(digits):]=digits[:]
    return ret
vec_int2base=np.vectorize(int2base)
vec_int2base(np.asarray([2,1,5]),base=3,size=3)

Was mit folgendem Fehler endet:

...
   1640             if ufunc.nout == 1:
   1641                 _res = array(outputs,
-> 1642                              copy=False, subok=True, dtype=otypes[0])
   1643             else:
   1644                 _res = tuple([array(_x, copy=False, subok=True, dtype=_t)

ValueError: setting an array element with a sequence. 

Gibt es einen besseren Weg, um ihn für den Vektorenfall zu schreiben, und was fehlt mir hier?

2voto

slightlynybbled Punkte 2278

Ich benutze die Funktion "fromBase10" (unten) ziemlich oft, während ich in der Assembly-Programmierung arbeite. Beachten Sie, dass sie die Ausgabe nicht auffüllt, aber numpy.vectorize damit funktioniert. Vergessen Sie einfach nicht, aufzufüllen.

## Führen Sie dies aus, um eine Basis 10 in eine beliebige Basis umzuwandeln
def fromBase10(number, base):
    if not number:
        return '0'
    sign = 1 if number > 0 else -1
    alphanum = string.digits + string.ascii_lowercase
    nums = alphanum[:base]
    res = ''
    number *= sign

    while number:
        number, mod = divmod(number, base)
        res += nums[mod]
    return ('' if sign == 1 else '-') + res[::-1]

Beachten Sie, dass ich die Grundroutine von jemand anderem auf Stack Exchange kopiert habe, aber ich erinnere mich nicht mehr, woher. Ich möchte einfach nicht Anspruch erheben, wo es nicht mir gehört :)

2voto

Warren Weckesser Punkte 101355

Hier ist eine vektorisierte Version:

import numpy as np

def int2base(x, basis, groesse=None, reihenfolge='absteigend'):
    x = np.asarray(x)
    if groesse is None:
        groesse = int(np.ceil(np.log(np.max(x))/np.log(basis)))
    if reihenfolge == "absteigend":
        potenzen = basis ** np.arange(groesse - 1, -1, -1)
    else:
        potenzen = basis ** np.arange(groesse)
    ziffern = (x.reshape(x.shape + (1,)) // potenzen) % basis
    return ziffern

Wenn x die Form shp hat, hat das Ergebnis die Form shp + (groesse,). Wenn groesse nicht gegeben ist, basiert die Größe auf dem größten Wert in x. Die reihenfolge bestimmt die Reihenfolge der Ziffern; verwenden Sie reihenfolge="absteigend" (Standard) um beispielsweise 123 in [1, 2, 3] umzuwandeln. Verwenden Sie reihenfolge="aufsteigend" um [3, 2, 1] zu erhalten. (Letzteres könnte natürlicher sein, da der Index der Ziffer im Ergebnis der Potenz der Basis für diese Ziffer entspricht.)

Beispiele:

In [97]: int2base([255, 987654321], 10)
Out[97]: 
array([[0, 0, 0, 0, 0, 0, 2, 5, 5],
       [9, 8, 7, 6, 5, 4, 3, 2, 1]])

In [98]: int2base([255, 987654321], 10, groesse=12)
Out[98]: 
array([[0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 5, 5],
       [0, 0, 0, 9, 8, 7, 6, 5, 4, 3, 2, 1]])

In [99]: int2base([255, 987654321], 10, reihenfolge="aufsteigend")
Out[99]: 
array([[5, 5, 2, 0, 0, 0, 0, 0, 0],
       [1, 2, 3, 4, 5, 6, 7, 8, 9]])

In [100]: int2base([255, 987654321], 16)
Out[100]: 
array([[ 0,  0,  0,  0,  0,  0, 15, 15],
       [ 3, 10, 13, 14,  6,  8, 11,  1]])

-1voto

Unknown Punkte 1

Danke Warren für diese vektorisierte Implementierung.

Ich habe eine weitere vektorisierte Implementierung basierend auf deiner erstellt, die effizienter ist.

def base_representation(x, base, size=None):
    x = np.asarray(x)
    if size is None:
        size = int(np.floor(np.log(np.max(x))/np.log(base)))+1
    arrays = []
    for _ in range(size):
        x, reminder = np.divmod(x, base)
        arrays.append(reminder)
    return np.stack(arrays, axis=-1)

Beachte, dass ein Fehler bei der Größe korrigiert wurde: Die Formel sollte lauten size=floor(log(x)/log(base))+1.

Beste Grüße.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X