Bitweise Shift In Basic.... Nicht Ganz So Trivial

  • Hallo,


    um bestimmte Algorithmen auch in BASIC zu implementieren, benötigt man oft bitweise "shift" (bits "schieben" um 1 oder mehrere Stellen links oder rechts im Binärsystem) .


    Bytes (0-255) so zu bearbeiten ist noch relativ trivial und effizient zu implementieren:


    10 PRINT "BITWISE SHIFT IN BASICA"
    20 INPUT "BYTE VALUE (0-255) ";A%
    30 PRINT "VALUE IN HEX=";HEX$(A%)
    40 B%=255 AND (A%+A%)
    50 PRINT "LEFT SHIFT=";HEX$(B%)
    60 REM BASICA ALWAYS TAKE NUMBERS AS A FLOAT !
    70 REM SO YOU MUST USE INT() FUNCTION TO GET AN INTEGER RESULT
    80 B%=INT(A%/2)
    90 PRINT "RIGHT SHIFT (HEX)=";HEX$(B%)


    Das was schon weniger effizient ist, die Division durch 2, ist schon häßlich, aber die Kröte schluckt man noch.


    Wenn man aber 16-Bit Integer bitweise "schieben" will, wird es richtig ineffizient, weil man scheinbar das nur noch mit FLOAT Rechenoperationen hinbekommt.


    10 PRINT "16-BIT INTEGER SHIFT IN BASICA"
    20 INPUT "INTEGER VALUE (0-65535) ";A
    30 IF A<>INT(A) THEN PRINT"FLOAT IS NOT THE SAME AS INTEGER.":GOTO 20
    40 IF A>65535! OR A<0! THEN PRINT"NOT IN INTEGER VALUE RANGE.":GOTO 20
    50 PRINT "VALUE IN HEX=";HEX$(A)
    60 B=A+A:IF B>65535! THEN B=B-65536!
    70 PRINT "LEFT SHIFT=";HEX$(B)
    80 REM BASICA ALWAYS TAKE NUMBERS AS A FLOAT !
    90 REM SO YOU MUST USE INT() FUNCTION TO GET AN INTEGER RESULT
    100 B=INT(A/2)
    110 PRINT "RIGHT SHIFT (HEX)=";HEX$(B)


    Hat jemand eine elegantere Idee zum Bearbeiten von 16-Bit Werten in BASIC ?

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

    • Offizieller Beitrag

    Moin moin

    Hat jemand eine elegantere Idee zum Bearbeiten von 16-Bit Werten in BASIC ?


    Gibt es ein bitweises UND?
    Welches BASIC benutzt du eigentlich?

  • Gibt es ein bitweises UND?


    Ich meine AND funktioniert bitweise. Kannst du ja mal an verschiedenen Werten für A und B testen: PRINT A AND B


    Zitat

    Welches BASIC benutzt du eigentlich?


    BASICA. Das ist ein Microsoft-BASIC für frühe IBM-PCs

    »It is practically impossible to teach good programming to students that have had a prior exposure to BASIC: as potential programmers they are mentally mutilated beyond hope of regeneration.« (Edsger W. Dijkstra)


    Homespage| Computerarchäologie | Blog | Forschung

    • Offizieller Beitrag

    Ich meine AND funktioniert bitweise. Kannst du ja mal an verschiedenen Werten für A und B testen: PRINT A AND B


    Dann ist es doch einfach:
    Shift links
    A = A + A
    A = A and 65535

  • Moin moin


    Gibt es ein bitweises UND?
    Welches BASIC benutzt du eigentlich?


    Bitweise gibt es AND, OR und XOR für BASICA/GWBASIC, welches ich benutze (weil es auf den ältesten IBM PCs auch noch gut läuft und sozusagen zur Originalausstattung der ersten PCs gehört hatte).


    Wenn man PowerBASIC z.B. nutzt, gibt es auch ein bitweises "Shift" als Operator. Mir ging's aber eher um die Möglichkeiten, was man noch tun kann, wenn man eben *nicht* den Shift-Operator in der Sprache hat.
    Eine Idee war auch, ein Assemblerprogramm einzubinden, wie z.B. das hier (Anhang). Aber das Beispielprogramm z.B. läuft nur mit QBASIC/QB 4.5, und kann auch nur 8-Bit und nicht 16-Bit Zahlen "bitweise schieben".


  • Dann ist es doch einfach:
    Shift links
    A = A + A
    A = A and 65535


    Nein. a) weil 65535 erstmal wieder ein FLOAT-Wert in BASIC ist (leider werden sozusagen alle Zahlen erstmal als FLOAT im Interpreter behandelt), und b) weil nur das Links-Shift "einfach" ist, Rechts-Shift ist mind. eine Division + Abschneiden der Nachkommastellen.
    Und die (Float) Division kostet Zeit, viel Zeit.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

    • Offizieller Beitrag

    Geht's dir um Geschwindigkeit oder um eine allgemeine Funktion?


    Wenn AND, OR, XOR doch bitweise arbeitet, ist es doch egal ob intern gefloatet wird oder nicht.
    Was gibt den folgendes aus?
    print 2 and 1
    print 3 and 1
    print 3.14 and 1


    Beim Links-Shift sollte das AND aber schneller sein als die Vergleiche in deinem ersten Post.
    Und den Rechts-Shift geht nicht besser.

  • Geht's dir um Geschwindigkeit oder um eine allgemeine Funktion?


    Erstmal um Geschwindigkeit, weil ich ein C-Sourcecode in BASIC übersetzen möchte, und in der C-Source wird innerhalb von Schleifen extensiv "geshifted".



    Kapier' ich nicht. AND, OR und XOR ist was anderes als die SHR/SHL bzw. die Schieberegister-Operation.
    D.h. auch wenn AND, OR und XOR funktionieren, kann ich noch lange nicht effizient bitweise schieben...

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

    • Offizieller Beitrag

    D.h. auch wenn AND, OR und XOR funktionieren, kann ich noch lange nicht effizient bitweise schieben...


    B = A + A; B = B and 65535
    ist aber effizienter als hier:

    60 B=A+A:IF B>65535! THEN B=B-65536!


    Ok, ein Geschwindigkeitsrekord gewinnst mit beiden nicht.
    Kann den BASICA Assembler aufrufen?



    und in der C-Source wird innerhalb von Schleifen extensiv "geshifted"


    Geht's den wirklich um Shifts, oder ist der Shift eine schnellere Umsetzung einer 2^n Multiplikation?


  • Kapier's weiterhin nicht was Du mir sagen willst. Ich hatte ja schon darauf hingewiesen, das BASICA/GWBASIC/QBASIC erstmal alle Zahlen (also auch die Zahl 65535) als FLOAT ansieht.
    Wenn Du "B AND 65535" in BASIC ausführst, ist das NICHT das Gleiche, wie wenn Du das z.B. in C (mit einem C Compiler) und dem Datentyp INTEGER machst.


    BASICA / QBASIC kann mit CALL bzw. USR() auch Assembler (im Interpreter) aufrufen. Dabei musst Du aber auch DEF SEG, VARSEG und VARPTR einsetzen. Außerdem musst Du im Assemblerteil natürlich erstmal den Stack retten, und die Parameterübergabe-Mechanik verstehen, dann Deine eigentlichen Berechnungen durchführen, die Parameter zurückgeben, und den Stack wiederherstellen - das RETF am Schluß nicht zu vergessen.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.

    • Offizieller Beitrag

    Mit "B AND 65535" will ich mir das "IF B>65535! THEN B=B-65536!" sparen.



    Bitweise gibt es AND, OR und XOR für BASICA/GWBASIC


    Wenn Du "B AND 65535" in BASIC ausführst, ist das NICHT das Gleiche, wie wenn Du das z.B. in C (mit einem C Compiler) und dem Datentyp INTEGER machst.


    Und das widerspricht sich !!!!
    Wenn AND bitweise arbeitet, sollte es wie in C mit Integern funktionieren. Wenn es das nicht tut, was macht es denn?

    Was gibt den folgendes aus?
    print 2 and 1
    print 3 and 1
    print 3.14 and 1

    • Offizieller Beitrag

    Doch, habe ich. Und hab's ich gerade am lebenden Objekt getestet.
    Allerdings war mir nicht mehr bewusst, das bei Zahlen >= 32768 ein Overflow auftritt.
    Anscheinend wird bei AND etc mit 16 bit Signed gearbeitet.
    Warum sagst du das nicht gleich. :)

  • ?


    Das ist so ähnlich wie die Idee, bei Zahlen über 32767 stattdessen negative Zahlen (im Bereich -1 bis -32767) zu nutzen.
    Ich habe aber - wenn ich mit Ganzzahlen (16 Bit, nicht 32 Bit) rechne, dann oft als Ergebnis negative Zahlen... mit einer Berechnung ohne Korrekturaddition wird's dann wieder schwierig.
    In meinem Beispiel-Code gibt man außerdem die Zahlen nicht als Hexadezimalwert ein. Mhhmmm vielleicht kann man ja HEX$() danach noch nutzen, aber das ist sicherlich auch eine Performancebremse.

    "The biggest communication problem is we do not listen to understand. We listen to reply." - Stephen Covey


    Webseite und Blog ist immer noch - seit fast 20 Jahren - online.