array auf inhalt überprüfen (is binary?)



  • Hi!

    Mit sscanf geht das kaum mit einem Compiler binär. Was du suchst ist strtoul,
    guckst du hier:

    char sbin[64]; 
    	unsigned long num;
    
    	strcpy ( sbin, "11110000" );
    	num = strtoul ( sbin, NULL, 2 );
    	printf ( "%lu\n", num );
    


  • Hallo,

    Funktioniert mit strtoul leider auch nicht bei mehr als 10bit.

    mfg Christoph



  • symbian schrieb:

    Hallo,
    Funktioniert mit strtoul leider auch nicht bei mehr als 10bit.
    mfg Christoph

    ich glaube du weist nicht was ein Bit ist, 10 Bit = 2 hoch 10 also 1024 im Dezimalsystem d.h. du kannst mit 10 bit die Zahlen von 0-1023 darstellen, nur weil du 10 einser hintereinander sind das noch lange keine 10 Bit



  • Hallo,

    Sry mein Fehler. Ich bin mir nur leider nicht ganz klar bei folgender Formulierung:
    ...Programm, welches binäre Zahlen (bis max 32-bit) von stdin zeilenweise einliest.

    Sind damit 32 bit Zeichen (01), oder eine dezimal Zahl aus 32 bit (=2^32 = 4294967296 = 10 Zeichen) gemeint?

    mfg Christoph



  • Klappt doch:

    strcpy ( sbin, "11111111111" ); // 11 Bit
    	num = strtoul ( sbin, NULL, 2 );
    	printf ( "%lu\n", num );
    
    	strcpy ( sbin, "1111111111111111" ); // 16 Bit
    	num = strtoul ( sbin, NULL, 2 );
    	printf ( "%lu\n", num );
    
    	strcpy ( sbin, "11111111111111111111111111111111" ); // 32 Bit
    	num = strtoul ( sbin, NULL, 2 );
    	printf ( "%lu\n", num );
    

    Vielleicht machst du etwas anderes falsch.
    Achte auch auf den Formatstring; "%lu" steht z.B. für unsigned long int, "%li" für signed long int.
    Gruß,
    B.B.



  • So wie ich das sehe läuft es darauf hinaus daß du einen String einliest der aus einsen und nullen besteht. Z.B.

    1010010110 = 1*2^9 + 0*2^8 + 1*2^7 + 0*2^6 + 0*2^5 + 1*2^4 + 0*2^3 + 1*2^2 + 1*2^1 + 0*2^0
    

    das waren jetzt halt mal nur 10 Bit für 32 Bit analog so weitermachen, den String fährst du halt Zeichen für Zeichen durch und addiert die Teile.

    u_int CalcBuffer(char *buffer){
    
    	int	len, i;
    	u_int	result=0;
    
    	len = strlen(buffer);
    	if(len > 32){
    		sprintf("Your String is Scheissendreck);
    		return 0;
    	}
    	for(i = len - 1; i >= 0; i--){
    		if((buffer[i] < 48) || (buffer[i] > 49)){
    			sprintf("Your String is Scheissendreck);
    			return 0;
    		}
    		result += (buffer[i] - 48)*(u_int)pow(2, (double)i);
    	}
    	return result;
    }
    


  • Hallo,

    Leider kann ich diese Variante nicht verwenden (ich muss den gesamten String zur weiterverarbeitung als 32 stellige Zahl einlesen). macht also 10^32 als benötigten maximalwert für die zahl. 10^32 entspricht 2^106.3...
    Also benötige ich einen Ganzzahl-Datentyp mit min 107bit, den es nach meinem Wissen leider nicht gibt.

    mfg Christoph



  • @B.B.

    hab gerade gemekert, dass mein problem bei strtoul darin besteht, dass ich die funktion falsch interpretiert habe. strtoul interpretiert den string als binärzahl und konvertiert diesen. Ich möchte aber die binärzahl 1:1 übernehmen. also dass dann in bin auch wirklich die zahl 110 steht und nicht eine konvertierte 6.

    mfg Christoph



  • symbian schrieb:

    Ich möchte aber die binärzahl 1:1 übernehmen. also dass dann in bin auch wirklich die zahl 110 steht und nicht eine konvertierte 6.

    hä? Das System legt sowieso alles im Binäermodus. '6' ist nur eine Darstellung auf dem Bildschirm für die dummen Menschen, die mit '110' nichts anfangen können. Also Wert der Zahl mit ihrer Darstellung nicht verwechseln!

    strtoul("110", NULL, 2) liefert die 110 zurück. Was soll es sonst zurückgeben?

    edit: wenn du nur überprüfen willst, ob die Eingabe tatsächlich nur eine Binärzahl hat und sonst keine andere Zeichen, dann kannst folgendes machen:

    char *endptr;
    strtoul(eingabe, &endptr, 2);
    if(*endptr)
    {
        printf("Alter, gib nur eine Binärzahl ein ohne weitere Zeichen!!!\n");
        ....
    }
    

    [klugscheisser]
    btw: muss ich jede Woche erklären, wie strtoul benutzt wird?
    [/klugscheisser]



  • Hallo,

    Ich glaub wir reden ein wenig aneinander vorbei:
    Das Problem ist der Datentyp. Ich benötige minimum 107bit für eine 32stellige Zahl. strtoul liest aber in einen unsigned long int ein. der hat aber nur 32bit=10stellige Zahl. (4294967295).

    (wegen dem "konvertierungsproblem": strtoul(str,NULL,2) konvertiert. strtoul(str,NULL,0) liefert den wert 1:1.)

    mfg Christoph



  • symbian schrieb:

    Hallo,

    Leider kann ich diese Variante nicht verwenden (ich muss den gesamten String zur weiterverarbeitung als 32 stellige Zahl einlesen). macht also 10^32 als benötigten maximalwert für die zahl. 10^32 entspricht 2^106.3...
    Also benötige ich einen Ganzzahl-Datentyp mit min 107bit, den es nach meinem Wissen leider nicht gibt.

    mfg Christoph

    Nimmsu 4 unsigned long, z.B. als Array.
    Gruß,
    B.B.



  • symbian schrieb:

    Hallo,

    Ich glaub wir reden ein wenig aneinander vorbei:
    Das Problem ist der Datentyp. Ich benötige minimum 107bit für eine 32stellige Zahl. strtoul liest aber in einen unsigned long int ein. der hat aber nur 32bit=10stellige Zahl. (4294967295).

    (wegen dem "konvertierungsproblem": strtoul(str,NULL,2) konvertiert. strtoul(str,NULL,0) liefert den wert 1:1.)

    mfg Christoph

    strtoul mi 0 an Ende entscheidet autoamatisch, welches Zahlsystem er nimmt, bei einer 2 zwingst du dem System das dual System, das ist der große Unterschied.

    strtoull liefert ein unsigned long long int was in der Regel uint64_t darstellt. Wenn du aber 107 bits brauchst, dann gibt es keine Standardfunktion, die 107 bit breite Zahlen zurückliefert. Also muss du deine Eingabe selber splitten und 2 Mal strtoull aufrufen.



  • symbian schrieb:

    ... Ich benötige minimum 107bit für eine 32stellige Zahl. strtoul liest aber in einen unsigned long int ein. der hat aber nur 32bit=10stellige Zahl. (4294967295).
    mfg Christoph

    Wozu willst du den String in ein biäres Format quetschen?
    Wozu ist das gut?
    😕



  • Hallo Chritoph,

    Du möchtest also erreichen, daß überall wo deine Zeichenkette eine '1' enthält, das zugehörige Bit in der Integerzahl gesetzt wird und da, wo in deiner Zeichenkette eine '0' steht, das zugehörige Bit zurückgesetzt wird?

    Dann ist mir noch nicht gan klar, wie du auf eine Zahl mit 107 Bit kommst? Wie kommt die '107' zustande?

    Zur Klärung der Probleme hier ist wichtig zu wissen, was du mit der umgewandelten Zahl anstellen möchtest. Wenn du vor hast, mit was längerem als 'unsigned long' zu rechnen, dann viel Spaß. Die benötigten Funktionen mußt du dir dann wohl alle selbst schreiben oder eine gute Bibliothek finden. Aber ich glaube, das ist von dir nicht so gewollt.

    mfg Mario



  • Hallo,

    Ich möchte die eingelesenen (32 stelligen) Zahl verwenden um diese dann in decimal und hex zu konvertieren (ich weiß, dass es mit array funktioniert), aber ich würde es gerne numerisch machen:

    z.b. in dec

    for(bit=0,dec=0,exp=0;bin>0;)
    {
    		 bit=bin%10;
    		 bin/=10;
    		 for(i=0;i<exp;i++)bit*=2;
    		 dec+=bit;
    		 exp++;
    }
    

    Die 107bit kommen daher, dass die größte 32stellige Zahl 2^106.3 ist
    also 107bit benötigt um dargestellt zu werden.

    mfg christoph



  • Hallo Christoph,

    du bist dir sicher, daß du eine 32 stellige Dezimalzahl meinst?
    Bisher war immer die Rede von einer 32 stelligen Binärzahl. Und die paßt in einen unsigned long - ein Bit je Stelle.

    Willst du mit größeren Zahlen als 2^32 arbeiten, sieh dir mal die folgende Bibliothek an: GNU MP Bignum Library.
    Informationen zu dieser Bibliothek und die Bibliothek selbst findest du unter http://gmplib.org

    mfg Mario



  • Dies ist zwar keine 32 stellige Zahl, aber das Prinzip ist das gleiche:
    1348 = 8100 + 4101 + 3 * 102 + 1 * 103

    Daraus möchtest du nun ein binäres Format erzeugen ( warum auch immer 😃 ). Müsste man sich vorher überlegen, wie die Einsen und Nullen gespeichert werden sollen.
    So:
    typedef unsigned long uint128[4]; 128 Bit Typ
    Oder so:
    typedef unsigned char uint[128]; '128 Bit' Typ

    Die zweite Variante dürfte handlicher und schneller in der Ausführung sein ( Vermutung ). Braucht etwas mehr Speicher, aber wen juckts.
    Ist die Zahl erstmal konvertiert, kannst du sie immer noch recht einfach in den ersten Typ umwandeln.

    Gruß,
    c.



  • coverter schrieb:

    Dies ist zwar keine 32 stellige Zahl, aber das Prinzip ist das gleiche:
    1348 = 8100 + 4101 + 3 * 102 + 1 * 103

    Die 10n verursachen bei n = 10 eine Überschreitung des unsigned long Wertebereichs. Denn: 1010 > ULONG_MAX.

    Du könntest z.B. die Zehnerpotenzen so bilden:
    Nimm einen geeigneten Datentypen, z.B

    #define BITS 128
    typedef unsigned char uint128[BITS];
    

    Setze das LSB auf 1. Dann multipliziere in jedem Durchlauf binär mit 10.
    So bildest du in jedem Durchlauf die Zehnerpotenzen (100,101,102, usw.)

    Die einzelnen Zahlen der zu konvertierenden Zahl kannst du leicht ins Binäre übertragen, denn eine einzelne Zahl kann ja nicht größer als 9 Werden. Diese Zahlen multiplizierst du in jedem Durchlauf mit der zugehörigen Zehnerpotenz im Binären und addierst diese zum Ergebnis.

    Dies ist eine Möglichkeit, die mir einfällt, wie man 32 stellige Zahlen ins Binäre überführen kann. Man kann auch wesentlich größere Zahlen bearbeiten, wenn man die BITS entsprechend höher schraubt.

    Gruß, mr. a.



  • Hallo Christoph,

    langsam dämmert mir, wo du hin willst.
    mit deinem Konstrukt

    bit=bin%10;
       bin/=10;
    

    machst du ja nichts anderes als rauszukriegen, an welcher Stelle - von hinten beginnend - deine eingegebene 'Binärzahl' eine '1' enthält.
    Diese '1'multiplizierst du dann mit der Stellenwertigkeit (2^exp):

    for(i=0;i<exp;i++)bit*=2;
    

    und adierst das ganze letztendlich zu deinem Ergebnis:

    dec+=bit;
    

    An welcher Stelle in der Binärzahl eine '1' steht, kannst du schon mit dem C-String aus deiner Eingabe rauskriegen:
    Du übergibst also deinen C-String an die Funktion und kopierst den Zeiger auf den Anfang des C-Strings. Den brauchen wir, um zu erkennen, wann der gesamte C-String mit deiner Binärzahl umgewandelt ist.
    Dann suchst du das Ende deiner 'Binärzahl' (Ende des C-Strings: '\0') mit dem kopierten Zeiger und stellst den Zeiger dann um eins zurück auf die letzte Stelle deiner Binärzahl - wir beginnen also auch hier von hinten!:

    unsigned long binToDec (char * bin)
       {
       char * digit = bin;
       while (*digit != '\0') ++digit;
       --digit;
    

    Jetzt brauchen wir noch zwei Variablen; eine für das Umwandlungsergebnis und eine für die Stellenwertigkeit (ich nehme hier gleich die Stellenwertigkeit, da es die Berechnungen erleichtert. Du kannst genauso den Exponenten als Variable Wählen und dann mit 2^exp die Stellenwertigkeit errechnen). Die Stellenwertigkeit initialisiere ich mit 'weight=1', da ich mit der letzten (niederwertigsten) Stelle der Binärzahl beginne und diese die Wertigkeit 1 hat.:

    unsigned long dec = 0;
       unsigned long weight=1;
    

    Soweit die Vorbereitung. Jetzt kommt es zur eigentlichen Umwandlung.
    Dabei durchlaufen wir die Binärzahl in deinem C-String von hinten nach vorne mit dem Zeiger 'digit', bis wir die erste Stelle der Binärzahl in die Berechnung einbezogen haben ('bin <= digit').
    Zuerst prüfen wir, ob an der aktuellen Stelle der Binärzahl eine '1' steht. Nur dann müssen wir die Wertigkeit der Stelle zum Dezimalwert addieren ('dec += weight').
    zum Schluß wird der Zeiger 'digit' auf eine Stelle weiter vorn gesetzt ('--digit') und die zugehörige Wertigkeit dieser Stelle berechnet, die ja doppelt so groß ist wie die zuvor betrachtete ('weight *= 2'):

    while (bin <= digit)
          {
          if (*digit == '1')
             {
             dec += weight;
             };
          --digit
          weight *= 2;
          };
    

    Das war's dann schon mit der Umwandlung von binär nach dezimal. Jetzt muß nur noch der errechnete Dezimalwert zurückgegeben werden:

    return dec;
       };
    

    Und nun nochmal alles zusammen:

    unsigned long binToDec (char * bin)
       {
       char * digit = bin;
       while (*digit != '\0') ++digit;
       --digit;
    
       unsigned long dec = 0;
       unsigned long weight=1;
    
       while (bin <= digit)
          {
          if (*digit == '1')
             {
             dec += weight;
             };
          --digit;
          weight *= 2;
          };
    
       return dec;
       };
    

    mfg Mario



  • mario_69 schrieb:

    ...
    machst du ja nichts anderes als rauszukriegen, an welcher Stelle - von hinten beginnend - deine eingegebene 'Binärzahl' eine '1' enthält.
    ...
    mfg Mario

    Es wird doch eine Dezimalzahl eingegeben? 😕


Anmelden zum Antworten