Dezimalzahl in eine Basis umwandeln

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Antworten
nenagzb
User
Beiträge: 17
Registriert: Donnerstag 16. Oktober 2014, 22:01

Also, meine Aufgabe ist es Python so zu programmieren, dass man dann zwei Zahlen eingeben muss. Einmal eine Dezimalzahl und dann eine Basis, die auch aus Buchstaben bestehen darf. Die Dezimalzahl soll dann in das Zahlensystem der Basis umgewandelt werden.
Ja, meine Idee das umzusetzen ist bestimmt super kompliziert, aber ich habe eben nicht so viele Kenntnisse.
Die Dezimalzahl soll x sein und die Basis n.
Was ich gefunden habe und was man benötigt ist einmal die Länge der Basis: len(n)
Durch diese Zahl muss man ja die Dezimalzahl teilen und den Rest nehmen.
Dann noch das modulo, also %.
x%len(n)
Dann habe ich mir überlegt eine Schleife zu machen, in der ich x%len(n) berechne. Da muss ich aber die Schrittgröße irgendwie verändern, so dass nicht alle Zahlen in 1er Schritten von x bis 0 durchgegangen werden... und da muss ich wissen wie man das macht.. und wie man die einzelnen Ergebnisse abspeichert, so dass man die dann alle am Ende nebeneinander "printen" kann..
Das ist mein Code bis jetzt...

Code: Alles auswählen

from sys import stdin
for line in stdin:
    x,n=[str(line)for line in line.split()]
    sum=0
    for i in range (0,int(x)):
            sum+=i%(len(n))
    print(sum)
Da steht zwar sum.. ich weiß aber dass das falsch ist. ich wusste nur nicht, was ich dahin schreiben soll und habe da aber was hingeschrieben, um den Algorithmus austesten zu können... Denn dann drücke ich F5 und gebe was für x und n ein und bekomme dann entweder eine Fehlermeldung oder nicht..
Zuletzt geändert von Anonymous am Samstag 25. Oktober 2014, 23:17, insgesamt 1-mal geändert.
Grund: Quelltext in Python-Code-Tags gesetzt.
BlackJack

@nenagzb: Die Basis darf aus Buchstaben bestehen? Das glaube ich nicht. Es ist wohl eher so das die Ziffern für die gewählte Basis auch mehr als 10 sein dürfen und man deshalb nicht mit den Dezimalziffern 0 bis 9 auskommt und man dann auch Buchstaben hinzunehmen darf/muss.

Man braucht die Länge der Basis? Was soll das denn bedeuten? Was Du anscheinand machen willst ist die Länge der Eingabe der Basis als Zeichenkette zu nehmen. Bei der Basis 2 wäre die Länge also 1. Und bei der Basis 8 wäre die Länge auch 1. Genau wie bei jeder Basis die man mit einer Ziffer beschreiben kann. Da wäre also das Ergebnis immer gleich. Das kann es ja wohl nicht sein.

Das `i` macht keinen Sinn denn Du musst ja die Zahl `x` umwandeln. Eine Schrittweite wird da auch nicht weiterhelfen. Die Abbruchbedingung ist eher das die gesamte Zahl umgewandelt wurde. Man kann zwar vorher ausrechnen wie viele Stellen das werden, aber eine ``while``-Schleife die prüft ob man fertig ist, kann man einfacher schreiben. Du brauchst eine Schleife die in jedem Durchgang eine weitere Ziffer berechnet und den Zahlenwert entsprechend verändert. Das Ergebnis ist auch keine Zahl sondern eine Folge von Ziffern, die man zum Beispiel in einer Liste sammeln kann. Die übliche Vorgehensweise ist, dass man den Dezimalwert der letzten Ziffer bekommt in dem man den Rest der Division der Zahl durch die Basis berechnet. Und wenn man die Zahl durch die Basis teilt und nur den ganzzahligen Anteil behält bekommt man den Zahlwert der ohne die letzte Ziffer übrig bleibt. Da man sowohl ganzzahlige Division als auch deren Rest benötigt, bietet sich die `divmod()`-Funktion an.

Beispiel: 42 als Dezimalzahl: Teilen durch Basis 10 = 4 und Rest 2. Teilen der 4 durch 10 = 0 und Rest 4. Gibt also die Ziffernfolge 42₁₀.

Zur Basis 8 wäre das Teilen durch 8 = 5 und Rest 2. Teilen der 5 durch 8 = 0 und Rest 5, also die Ziffernfolge 52₈.

Basis 16: Teilen durch 16 = 2 und Rest 10. Teilen der 2 durch 16 = 0 und Rest 2. Da die 10 nicht in eine Dezimalziffer passt muss man auf Buchstaben zurückgreifen. Dafür nimmt man A für den Wert 10, B für den Wert 11, und so weiter. Das Ergebnis ist also 2A₁₆.

Um einen Wert in eine Ziffer umzuwandeln kann man für die Werte 0 bis 9 einfach die `str()`-Funktion verwenden. Für grössere Werte kann man zum Beispiel den Index in eine passende Konstante aus dem `string`-Modul aus dem Wert berechnen. Oder sich den Umstand zunutze machen das für den Rechner letztendlich auch Zeichen nur Zahlen sind und man mit den den Funktionen `ord()` und `chr()` zwischen Zeichen und zugeordneter Zahl umrechnen kann und dass alphabetisch aufeinanderfolgende Zeichen (in der Regel) auch durch aufeinanderfolgende Zahlen repräsentiert werden.
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Weil ihr das mit der Zusammenarbeit wohl noch immer nicht verstanden habt:
http://www.python-forum.de/viewtopic.php?f=1&t=34949
Das Leben ist wie ein Tennisball.
Immortalmemo
User
Beiträge: 13
Registriert: Mittwoch 22. Oktober 2014, 00:02
Wohnort: Berlin

Code: Alles auswählen

#!/usr/bin/env python3
 from sys import stdin
 
for line in stdin:
        x,b=(int(word) for word in line.split())       
        while x > 0:  
                l=[]
                xi=x%b
                x=x//b
                l.append(xi)
       print(l)
Diesen Code hatte ich in einem anderen Beitrag gepostet. Allerdings gibt er mir für 42 zur basis 4 2 aus. Ich weiß nicht wie ich es schaffe dass er alle Reste ausgibt und auch in "umgekehrter Reihenfolge".
Dem Ergebnis nach urzuteilen hört er nach einem Schleifendurchgang auf bzw gibt nur das Ergebnis des 1. Durchlaufs aus.
Ich weiß nicht wie ich das ändern kann.

Ich möchte ja außerdem die neue Zahl nicht als Liste sondern als String ausgeben. (Ich kriege hier noch am Ende immer die eckigen Klammern)
Ich habe mir ein paar String-Methoden angeguckt und denke ich kriege das hin mit s.join(seq) hin.

Bin ziemlich ratlos, da ich vorher noch nie programmiert habe :/ und in der Vorlesung wurde leider auch nicht viel bisher gemacht.
BlackJack

@Immortalmemo: Geh das Programm mal Schritt für Schritt durch und dann solltest Du sehen warum die Liste immer nur ein Element enthalten kann. Du bekommst nicht die Ziffer aus dem ersten Schleifendurchlauf sondern die aus dem letzten.

Die Reihenfolge der Elemente in einer Liste kann man mit einer Methode auf Listen umkehren.
Immortalmemo
User
Beiträge: 13
Registriert: Mittwoch 22. Oktober 2014, 00:02
Wohnort: Berlin

Ich versuchs mal anhand des Beispiels x=42 b=10.

42>0
Initialisiere leere Liste l=[]
xi=42%10=2
x=42/10=4
l=[2]

4>0
Initialisiere l=[]
xi=4%10=4
x=4/10=0
l=[4]

Ausgabe 4.

Hier endet alles.

Aber ich weiß jetzt warum meine Liste nur ein Element ausgibt, weil ich in jedem Schleifendurchlauf immer wieder einen leere Liste initialisiere und diesen dann fülle. Als Ausgabe erhalte ich wie du sagtest wirklich nur den Wert vom letzten Durchlauf.

Hier mein verbesserter Code:

Code: Alles auswählen

#!/usr/bin/env python3

from sys import stdin
 

for line in stdin:
		x,b=(int(word) for word in line.split())   
		l=[]
		while x>0:
			xi=x%b
			x=x//b
			l.append(xi)
			l.reverse()	
		print(l)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Der funktioniert so nicht. Denk mal über Zeile 13 nach und rechne ein Beispiel mit einer dreistelligen Zahl und einer vierstelligen Zahl. Als Basis kannst du die 10 verwenden.
Das Leben ist wie ein Tennisball.
Immortalmemo
User
Beiträge: 13
Registriert: Mittwoch 22. Oktober 2014, 00:02
Wohnort: Berlin

Du hast Recht. Das funktioniert wirklich nicht, da ich in jedem Durchlauf die Liste umkehre komme ich z.B. bei x=320 b=10
1. Durchlauf: l=[0]
2.Durchlauf : l=[0,2] umdrehen ergibt [2,0]
3. Durchlauf : l=[2,0,3] umdrehen ergibt [3,0,2]
Richtig wäre: [3,2,0]

Ich habs gefixt, indem ich nun reversed komplett weggelasse habe. Habe stattdessen

Code: Alles auswählen

print(l[::,-1]) 
benutzt.

Für normale Zahlen funktioniert das problemlos nun.

In meiner Aufgabe allerdings, soll ich auch für
x=1024 und b=01 die Ausgabe= 1000000000000
x=1012 b=aAbBcCdDeEfF Ausgabe=Dac
x=3 b= 012 Ausgabe=10
x=0 b=1234567890 Ausgabe =1

rauskriegen.

Außerdem weiß ich nicht, wie ich die Zahlen nebeneinander ausgeben kann. Also nicht so [1,0,2,4].
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Immortalmemo hat geschrieben:Ich habs gefixt, indem ich nun reversed komplett weggelasse habe. Habe stattdessen

Code: Alles auswählen

print(l[::,-1]) 
benutzt.
Der fehler lag nicht am reverse, sondern an der Position des reverse. Es hätte einfach nur nicht in der Schleife stehen dürfen. ``l.reverse()`` und ``x[::1]`` sind übrigens zwei verschiedene Dinge. Der Erste Befehl verändert die Liste, der zweite erstellt eine neue.
Immortalmemo hat geschrieben:Für normale Zahlen funktioniert das problemlos nun.

In meiner Aufgabe allerdings, soll ich auch für
[...]
rauskriegen.
Und wo genau liegt da momentan dein Problem? Mit len bekommst du die Länge einer Zeichenkette raus, damit kannst du die Basis bestimmen. Mehr brauchst du doch nicht.
Immortalmemo hat geschrieben:Außerdem weiß ich nicht, wie ich die Zahlen nebeneinander ausgeben kann. Also nicht so [1,0,2,4].
Mittels join:

Code: Alles auswählen

>>> "".join(["spam", "ham", "and", "eggs"])
'spamhamandeggs'
Vorher musst du die Zahlen natürlich in Strings umwandeln, aber das bekommst du sicher hin.
Das Leben ist wie ein Tennisball.
BlackJack

Vollkommen OffTopic: So kann man das als 16-bit Assembler-Programm für DOS machen: http://www.python-forum.de/pastebin.php?mode=view&s=409 (NASM)

Testlauf:

Code: Alles auswählen

320 0123456789
320
1024 01
10000000000
1012 aAbBcCdDeEfF
Dac
3 012
10
0 1234567890
0
ab
Expected space after number.
42
Expected space after number.
42 0
Digits must be at least of length 2.
100000 01
Number is greater than 65535.
23 aab
Digits must be unique.
Die ungeraden Zeilen sind jeweils die Eingaben und die geraden die Ausgaben vom Programm. :-)
EyDu
User
Beiträge: 4881
Registriert: Donnerstag 20. Juli 2006, 23:06
Wohnort: Berlin

Übersichtlicher bekomme ich es nicht nicht:

Code: Alles auswählen

z = lambda a,b,v:(lambda a,s:(lambda g,a,s:g(g,a,s))(lambda g,a,s:(lambda g,a,s,h,t:a[h]+[g,lambda g,a,s:""][not t](g,a,t))(g,a,s,s[0],s[1:]),a,s))(a,(lambda b,v:(lambda f,b,v:f(f,b,v))(lambda f,b,v:(lambda f,b,v,d:[lambda f,b,v:[],f][d>0](f,b,d)+[v%b])(f,b,v,v/b),b,v))(b,v))

print z("01", 2, 42)
print z("012", 3, 42)
Nun in kürzer, interaktiv, ohne int-, bool- oder split-Aufrufe:

Code: Alles auswählen

from __future__ import print_function

(lambda a:(lambda f,a:f(f,a))(lambda f,a:(lambda f,a,i:[lambda f,a,i:(print((lambda a,l:(lambda(b,v),d:(lambda a,b,v:(lambda f,a,b,v:f(f,a,b,v))(lambda f,a,b,v:(lambda f,a,b,v,d:[lambda f,a,b,v:"",f][d>0](f,a,b,d)+a[v%b])(f,a,b,v,v/b),a,b,v))(a,d(b),d(v)))((lambda w:(lambda f,w:f(f,w,"",[]))(lambda f,w,c,o:[lambda f,w,c,o:[o,o+[c]][c!=""],lambda f,w,c,o:(lambda f,w,c,o,h:[lambda f,w,c,o,h,t:f(f,t,c+h,o),lambda f,w,c,o,h,t:f(f,t,"",[o,o+[c]][c!=""])][h==" "](f,w,c,o,h,w[1:]))(f,w,c,o,w[0])][w!=""](f,w,c,o),w))(l), (lambda n:(lambda f,n,e:f(f,n,e))(lambda f,n,e:[lambda f,n,e:f(f,n[1:],e*10+(lambda c:(lambda f,c,u,v:f(f,c,u,v))(lambda f,c,u,v:[lambda f,c,u,v:f(f,c,u+1,v[1:]),lambda f,c,u,v:u][c==v[0]](f,c,u,v),c,0,"0123456789"))(n[0])),lambda f,n,e:e][not n](f,n,e),n,0))))(a,i)),f(f,a)),lambda f,a,i:None][not i](f,a,i))(f,a,raw_input()),a))("0123456789ABCDEF")
Schöne Übung: Behandlung von fehlerhaften Eingaben.
Das Leben ist wie ein Tennisball.
Almarako
User
Beiträge: 1
Registriert: Donnerstag 4. März 2021, 14:30

soweit bin ich jetzt alleine schon gekommen, wie kann ich den if elif else teil verkürzen sodass ich nicht für alle 26 buchstaben ne eigene elif schreiben muss?

Code: Alles auswählen

Zahl = int(input("Nenne die Dezimalzahl  " ))

Base = int(input("Wähle die Basis  ")) 

Quotient = int(Zahl / Base)

while Quotient != 0: 
    Rest = Zahl % Base

    Quotient = int(Zahl / Base)

    if Rest == 10:
        print (str("A"))
    elif Rest == 11:
        print (str("B"))
    elif Rest == 12:
        print (str("C"))
    elif Rest == 13:
        print (str("D"))
    elif Rest == 14:
        print (str("E"))
    elif Rest == 15:
        print (str("F"))
    else:
        print (int(Rest))

    Zahl = Quotient
Sirius3
User
Beiträge: 17750
Registriert: Sonntag 21. Oktober 2012, 17:20

Statt einer Floatingpoint-Division und dann int, solltest Du gleich eine Ganzzahldivision // machen, bzw. da Du eh auch den Rest brauchst, divmod.
Um Ziffern in ihre Darstellung umzuwandeln, könnte man über eine Lookup-Tabelle gehen.

Code: Alles auswählen

import string
LOOKUP = string.digits + string.ascii_uppercase

zahl = int(input("Nenne die Dezimalzahl  " ))
base = int(input("Wähle die Basis  ")) 

while True:
    zahl, rest = divmod(zahl, base)
    print(LOOKUP[rest])
Antworten