Δευτέρα, 21 Δεκεμβρίου 2015

Εργασίες με δυαδικό

Σε αυτό το παράδειγμα εμπλουτίζουμε ένα πρόγραμμα από παλαιότερη ανάρτηση: Μετατροπή σε Δυαδικό
Φτιάχνουμε μια φόρμα οθόνης 100 χαρακτήρες επί 48 γραμμές, για να βλέπουμε τα αποτελέσματα (χρησιμοποιώ μη αναλογική γραφή, το ένα γράμμα κάτω από το άλλο).

Η συνάρτηση δυαδ$() πήρε μια παράμετρο προεραιτική, το πόσα byte θα δείχνει. Π.χ. το πρώτο, τα δυο πρώτα, τα τρία πρώτα ή όλα (και τα τέσσερα), ενός 32 bit Unsign Αριθμού. Δηλαδή χωρίς πρόσημο. Η συνάρτηση που κάνει την μετατροπή πρώτα σε δεκαεξαδικό Δεκαεξ() αν πάρει αρνητικό τον κάνει θετικό (παίρνει δηλαδή την απόλυτη τιμή).

Υπάρχει συνάρτηση που κάνει την μετατροπή ώστε ένας ακέραιος αρνητικός να μετατραπεί σε έναν unsign (χωρίς πρόσημο) με ίδια bits. H Δυαδικό.Ακέραιο() δίνει τον Unsign με ίδια bits, και η Ακέραιο.Δυαδικό() έναν Unsign τον κάνει με πρόσημο (στα ίδια bits).
Εδώ δείχνω τη διαφορά αναστροφής των bits (από 1 σε 0 και το ανάποδο) με το αντίστροφο. Το αντίστροφο ενός αριθμού με πρόσημο Α είναι το -Α. Αντίστροφο δεν έχουμε σε αναπαράσταση χωρίς πρόσημο. Αναστροφή των Bits όμως μπορούμε να κάνουμε.

Δείτε ποια είναι η διαφορά αν προσθέσουμε τον unsign A με τον αντίστροφο θα πάρουμε ένα  δυαδικό με όλα τα Bit 1. Αυτός όμως σε sign integer είναι ο -1.  Αν προσθέσουμε τον θετικό sign Α με τον sign - A τότε θα πάρουμε το 0, δηλαδή όλα τα bit 0.
Όπως γίνεται φανερό ο -Α, με Α θετική τιμή, έχει μια αναπαράσταση σε Bits το συμπλήρωμα του 2 στην τιμή του Unsign με τα ίδια bits.

To δυαδικό.από() είναι το Xor, και βλέπουμε μια χρησιμότητα στο να αντιστρέφουμε όχι μόνο όλο τον unsign αριθμό αλλά και όποια bit θέλουμε.

Βλέπουμε την Δυαδικό.Ολίσθηση και Δυαδική.Περιστροφή  (εδώ η λέξη δυαδικό στο πρόθεμα της περιστροφής έχει γίνει δυαδική...και δεν θυμάμαι την σκοπιμότητα...αλλά ας το δεχτούμε έτσι). Οι αρνητικές τιμές κάνουν την ολίσθηση και την περιστροφή προς τα δεξιά (32bit) και οι θετικές στα αριστερά (από 31 ... -31).

Οι μεταβλητές είναι πραγματικές αλλά τις χρησιμοποιούμε ως ακέραιες. Υπάρχει και ο συμβολισμός με το % όπου το Α%=2.5 θα πάρει το ακέραιο μέρος μόνο (εσωτερικά είναι πάλι πραγματική).
Μπορούμε να δηλώσουμε Μακρυς Α και να έχουμε έναν 32bit Long, όμως η χρησιμότητά του για τη Μ2000 είναι για να περνάμε τιμές σε κλήσεις εξωτερικών ρουτινών (dll).
H Για {} δουλεύει και με τους τρεις τύπους, (πραγματικός, ακέραιος, μακρύς). Αλλά δεν έχουμε κάποιο κέρδος σε ταχύτητα (ή είναι πολύ μικρό). Δεν συμβαίνει αυτό σε γλώσσες με compiler. Η Μ2000 τρέχει άμεσα διερμηνεύοντας το κείμενο.

Αν θέλουμε βάζουμε την ανανέωση της οθόνης να γίνεται ας πούμε κάθε 0,3 του δευτερολέπτου. Οπότε η εκτύπωσε φαίνεται να γίνεται μια φορά! (οι μονάδες είναι σε χιλιοστά του δευτερολέπτου. χωρίς τιμή το περιβάλλον κάνει άμεση ανανέωση οθόνης. Ουσιαστικά υπάρχει διπλή οθόνη αυτή που βλέπουμε και αυτή που ετοιμάζεται)
Σε wine μπορεί η γραμματοσειρά tahoma να μην είναι unicode. Σε αυτήν την περίπτωση πρέπει να δώσουμε το greek ή Ελληνικά για να χρησιμοποιηθεί σωστά. Έγινε αλλαγή το tahoma σε verdana που είναι unicode σε κάθε περίπτωση. (όταν δεν είναι unicode τότε φορτώνεται η γραμματοσειρά ανάλογα με την επιλογή κωδικοσελίδας, οπότε τα ελληνικά γράμματα μπορεί να λείπουν και εμφανίζονται τα τετράγωνα στην θέση τους.

ανανέωση 300

\\ μπορούμε να βάλουμε μια Διάβασε β αντί να δώσουμε τιμή
\\ και έτσι αν το τμήμα λέγεται α τότε με α 12 καλούμε το τμήμα με παράμετρο 12
\\ με tab και alt tab μπορούμε να μετακινήσουμε πολλές γραμμές μαζί
\\ μπορούμε να μετακινούμε τις γραμμές σπρώχνωντας τες με το ποντίκι!
Γραμματοσειρά "Verdana"   
Πένα 14
Οθόνη 1
β = 12
Συνάρτηση δυαδ$ {
      Διάβασε μια_τιμή
      Αν Ταύτιση("Α") τότε {
            Διάβασε από_εδώ
           από_εδώ=2*(ακ(4-από_εδώ) υπολ 4+1)-1
      } Αλλιώς {
            από_εδώ=1
      }
            δεκαεξαδική$ = Δεκαεξ$( μια_τιμή, 4 )
      Πίνακας μια_τιμή$( 16 )
      μια_τιμή$( 0 ) = "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"
      Εγγραφο Αα$
      Για ι = από_εδώ Εως Μήκος( δεκαεξαδική$ )
            Αα$ = μια_τιμή$( Εκφρ( "0x" + Μες$( δεκαεξαδική$, ι, 1 ) ) )
      Επόμενο ι
      = Αα$
}
Φόρμα 100,48 \\ χαρακτήρες πλάτος
Τύπωσε "Μετατροπή Δυαδικού από το " ; β ; " σε 32bits:"
Τύπωσε δυαδ$( β )
Τύπωσε δυαδ$( Δυαδικό.Αντίστροφο( β ) ); " Συμπλήρωμα ως προς 1 του " ; β
Τύπωσε δυαδ$( Δυαδικό.Αντίστροφο( β ) + 1 ); " Συμπλήρωμα ως προς 2 του " ; β
Τύπωσε δυαδ$( δυαδικό.ακέραιο(-β)); " Το -12  είναι το συμπλήρωμα του 2, σε δυαδική αναπαράσταση"
Τύπωσε δυαδ$( 0x1000 ) ; " ή 0x1000 δεκαεξαδικό"
Τύπωσε δυαδ$( 0xFFFF1000 ) ; " ή 0xFFFF1000 δεκαεξαδικό"
Τύπωσε δυαδ$( #FFAA22 ) ; " #FFAA22 είναι το 0x22AAFF - έχουμε μια τιμή RGB (RED=255 ή 0xFF) "
     \\ είναι το FF το οποίο είναι το τρίτο byte και όχι το πρώτο.
Τύπωσε δυαδ$( 0xFFAA22 ); " το 0xFFAA22 δεν είναι ίδιο με το #FFAA22"  

     \\ Μπορούμε να τυπώσουμε στο δεκαεξαδικό όπως στην Τύπωσε τυπώνουμε στο δεκαδικό.
     \\ αρνητικές τιμές ή εκτός ορίων τυπώνονται με ???-
Δεκαέξ "ο αριθμός Χ=" ; 256, "το άθροισμα =" ; 0x0100 + 0xF0, "To 250067:", 250067
Δεκαέξ "Εδώ είναι το λάθος (βάλαμε αρνητικό):" ; - 1
Για Bytes=1 έως 4 {
      Τύπωσε Δεκαεξ$(123,Bytes), δυαδ$(123,Bytes)
}
Για Bit=1 έως 8 ανα 2 {
      Τύπωσε Δυαδ$(Δυαδικο.ολισθηση(123,Bit)); " Ολίσθηση αριστερά στο ";Bit;"o Bit"
}
Τύπωσε Δυαδ$(123) ; " Κανονικό - Αριθμός 123  ή 0x";Δεκαεξ$(123,1)
Για Bit=1 έως 4 {
      Τύπωσε Δυαδ$(Δυαδικη.περιστροφη(123,-Bit)) ; " Περιστροφή  δεξιά στο ";Bit;"o Bit"
}
α=Δυαδικη.περιστροφη(123,-4)
Τύπωσε μορφή$("Δυαδικός ως ακέραιος με πρόσημο: {0} και χωρίς {1}", ακέραιο.δυαδικό(α), α)
\\ αντιστροφή bits
Τύπωσε δυαδ$(δυαδικό.απο(α,0χffffffff)); " η πραγματική αναστροφή των Bits"
Τύπωσε δυαδ$(δυαδικό.αντιστροφο(α)); " Εδώ είναι λάθος το α έχει Unsign τιμή"
Τύπωσε "Το δυαδικό.αντίστροφο δουλεύει για αριθμούς με πρόσημο Sign και όχι Unsign"
Τύπωσε δυαδ$(δυαδικό.αντιστροφο(ακεραιο.δυαδικό(α))) ; " εκτός και αν το μετατρέπουμε σε Sign"
Τύπωσε δυαδ$(-1-(ακεραιο.δυαδικό(α))); " το ίδιο κανουμε και εδώ, επειδή ξέρουμε ότι ο α είναι αρνητικός"
Τύπωσε Δυαδ$(α)
Τύπωσε Δυαδ$(δυαδικό.και(α,0χff)); " διατηρούμε τα τελευταία δεξιά 8 bit, τα άλλα γίνονται 0"
Τύπωσε Δυαδ$(δυαδικό.και(α,0χff000000)); " διατηρούμε τα τελευταία αριστερά 8 bit, τα άλλα γίνονται 0"
Τύπωσε Δυαδ$(δυαδικό.η(α,0χAA00)); " κάνουμε συγκεκριμένα Bit 1"
Τύπωσε Δυαδ$(δυαδικό.απο(δυαδικό.η(α,0χAA00),0χF00)); " αντιστρέφουμε συγκεκριμένα bit"
Τύπωσε Δυαδ$(45)
Τύπωσε Δυαδ$(-45); " παίρνει την απόλυτη τιμή, δίνει ότι και η προηγούμενη"
Τύπωσε Δυαδ$(δυαδικό.ακεραιο(-45)); " δίνει το δυαδικό σε αναπαράσταση ακέραιου"
Τύπωσε μορφη$("Αριθμός χωρίς πρόσημο {0} που έχει τα ίδια bit με αυτόν {1}",δυαδικό.ακεραιο(-45), -45)




Στην έκδοση 8.2 αν 17 η συνάρτηση δυαδ$() γράφεται καλύτερα ως λάμδα συνάρτηση για να κρατάει μέσα της τον πίνακα μόνιμα, δηλαδή να μην τον δημιουργεί κάθε φόρα που εκτελούμε τη συνάρτηση. Φτιάχνουμε μια λάμδα που παράγει τη λάμδα που θέλουμε!



δυαδ0$=Λάμδα$ ->{
      \\ αυτή η λάμδα παράγει μια άλλη, που έχει τον πίνακα κρατημένο στο περιβάλλον της
      \\ δεν μπορούμε να επέμβουμε σε αυτόν, και είναι πια ένα αντικείμενο με έτοιμες τιμές.
      Πίνακας μια_τιμή$( 16 )
      μια_τιμή$( 0 ) = "0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111", "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"     
      \\ η δυαδ$ είναι μια λάμδα συνάρτηση που συλλαμβάνει τον πίνακα μια_τιμή$()
      \\ οπότε δεν χρειάζεται να  φτιάχνεται κάθε φορά!
      = λάμδα$ μια_τιμή$()->{
            Διάβασε μια_τιμή
            Αν Ταύτιση("Α") τότε {
                  Διάβασε από_εδώ
                 από_εδώ=2*(ακ(4-από_εδώ) υπολ 4+1)-1
            } Αλλιώς {
                  από_εδώ=1
            }
                  δεκαεξαδική$ = Δεκαεξ$( μια_τιμή, 4 )
            Εγγραφο Αα$
            Για ι = από_εδώ Εως Μήκος( δεκαεξαδική$ )
                  Αα$ = μια_τιμή$( Εκφρ( "0x" + Μες$( δεκαεξαδική$, ι, 1 ) ) )
            Επόμενο ι
            = Αα$
      }
}
δυαδ$=δυαδ0$()


Η άλλη περίπτωση είναι με την χρήση μιας Κατάστασης σε ένα αντικείμενο, χωρίς λάμδα συνάρτηση. Αντί να χρησιμοποιούμε την δυαδ.δ$() κάνουμε ένωση με μια νέα δυαδ$()
Η ένωση κάνει αυτό Βάλε &δυαδ.δ$() και μετά αυτό Διάβασε &δυαδ$(), δηλαδή βάζει την αναφορά της δυαδ.δ$() στην νέα δυαδ$()
Εδώ μπορούμε να επέμβουμε στην ομάδα μετά την χρήση της δυαδ$(), γιατί είναι ανοικτή στο πρόγραμμα, ενώ αν ήταν σε λάμδα συνάρτηση θα ήταν απροσπέλαστη από έξω. Και στην ομάδα μπορούμε να δηλώσουμε ιδιωτικά κάποια μέλη της, αλλά μπορεί να πάρει συναρτήσεις που να επεμβαίνουν σε αυτές ακόμα και προσωρινά.

Ομάδα δυαδ {
      Κατάσταση δυαδική_τιμή = 0:="0000",1:= "0001",2:= "0010", 3:="0011",4:= "0100", 5:="0101", 6:="0110", 7:="0111", 8:="1000", 9:="1001", "A":="1010", "B":="1011", "C":="1100", "D":="1101", "E":="1110", "F":="1111"    
      Συνάρτηση δ$ {
            Διάβασε μια_τιμή
            Αν Ταύτιση("Α") τότε {
                  Διάβασε από_εδώ
                 από_εδώ=2*(ακ(4-από_εδώ) υπολ 4+1)-1
            } Αλλιώς {
                  από_εδώ=1
            }
                  δεκαεξαδική$ = Δεκαεξ$( μια_τιμή, 4 )
            Εγγραφο Αα$
            Για ι = από_εδώ Εως Μήκος( δεκαεξαδική$ )
                  Αα$ =  .δυαδική_τιμή$( Μεσ$( δεκαεξαδική$, ι, 1 ) )
            Επόμενο ι
            = Αα$
      }
}
Ένωσε δυαδ.δ$() στο δυαδ$()