Μυστικά

Μυστικά

Άσκηση εκμάθησης

Εισαγωγή

Τα δυαδικά ψηφία αντιστοιχίζονται τελικά άμεσα με τα τρανζίστορ στον CPU ή τη RAM σου, και με το αν το καθένα είναι "ανοιχτό" ή "κλειστό".

Ο χειρισμός χαμηλού επιπέδου, που ανεπίσημα ονομάζεται "bit-twiddling", είναι ιδιαίτερα σημαντικός στις γλώσσες συστημάτων.

Οι γλώσσες υψηλού επιπέδου, όπως η Julia, συνήθως αφαιρούν τις περισσότερες από αυτές τις λεπτομέρειες. Ωστόσο, μια πλήρης σειρά πράξεων σε επίπεδο bit είναι διαθέσιμη στη βασική γλώσσα.

Σημείωση: Για να δεις ευανάγνωστη δυαδική έξοδο στο REPL, σχεδόν όλα τα παρακάτω παραδείγματα πρέπει να τυλιχτούν σε μια συνάρτηση bitstring(). Αυτό αποσπά την προσοχή οπτικά, οπότε οι περισσότερες εμφανίσεις αυτής της συνάρτησης έχουν αφαιρεθεί.

Πράξεις ολίσθησης bit

Οι ακέραιοι τύποι, προσημασμένοι ή απρόσημοι, μπορούν να αναπαρασταθούν ως μια συμβολοσειρά από μηδενικά και άσσους.

julia> bitstring(UInt8(5))
"00000101"

Οι ολισθήσεις bit απλώς μετακινούν τα πάντα αριστερά ή δεξιά κατά έναν καθορισμένο αριθμό θέσεων. Με τους τύπους UInt, κάποια bit πέφτουν από το ένα άκρο και το άλλο άκρο συμπληρώνεται με μηδενικά:

julia> ux::UInt8 = 5
5

julia> bitstring(ux)
"00000101"

julia> ux << 2 # left by 2
"00010100"

julia> ux >> 1 # right by 1
"00000010"

Κάθε ολίσθηση αριστερά διπλασιάζει την τιμή και κάθε ολίσθηση δεξιά την υποδιπλασιάζει (υπόκειται σε περικοπή). Αυτό είναι πιο εμφανές στη δεκαδική αναπαράσταση:

julia> 3 << 2
12

julia> 24 >> 3
3

Μια τέτοια ολίσθηση bit είναι πολύ πιο γρήγορη από την "κανονική" αριθμητική, κάτι που κάνει την τεχνική πολύ δημοφιλή στον προγραμματισμό χαμηλού επιπέδου.

Με τους προσημασμένους ακεραίους, πρέπει να είμαστε λίγο πιο προσεκτικοί.

Οι ολισθήσεις αριστερά είναι σχετικά απλές:

julia> sx = Int8(5)
5

julia> sx # positive integer
"00000101"

julia> sx << 2
"00010100"

julia> -sx # negative integer
"11111011"

julia> -sx << 2
"11101100"

Η ολίσθηση αριστερά θετικών προσημασμένων ακεραίων είναι επομένως ίδια όπως με τους απρόσημους ακεραίους.

Οι αρνητικές τιμές αποθηκεύονται σε μορφή συμπληρώματος ως προς δύο, που σημαίνει ότι το αριστερότερο bit είναι 1. Κανένα πρόβλημα για μια ολίσθηση αριστερά, αλλά όταν ολισθαίνουμε δεξιά, πώς συμπληρώνουμε τα αριστερότερα bit;

julia> sx >> 2 # simple for positive values!
"00000001"

julia> -sx # negative integer
"11111011"

julia> -sx >> 2 # pad with repeated sign bit
"11111110"

julia> -sx >>> 2 # pad with 0
"00111110"

Ο τελεστής >> εκτελεί αριθμητική ολίσθηση, διατηρώντας το bit προσήμου.

Ο τελεστής >>> εκτελεί λογική ολίσθηση, συμπληρώνοντας με μηδενικά σαν ο αριθμός να ήταν απρόσημος.

Λογική κατά bit

Είδαμε σε μια προηγούμενη Έννοια ότι οι τελεστές && (και), || (ή) και ! (όχι) χρησιμοποιούνται με Boolean τιμές.

Υπάρχουν αντίστοιχοι τελεστές & (and κατά bit), | (or κατά bit) και ~ (μια περισπωμένη, not κατά bit) για να συγκρίνουν τα bit δύο ακεραίων.

julia> 0b1011 & 0b0010 # bit is 1 in both numbers
"00000010"

julia> 0b1011 | 0b0010 # bit is 1 in at least one number
"00001011"

julia> ~0b1011 # flip all bits
"11110100"

julia> xor(0b1011, 0b0010) # bit is 1 in exactly one number, not both
"00001001"

Εδώ, το xor() είναι το αποκλειστικό ή, χρησιμοποιημένο ως συνάρτηση.

Οδηγίες

Ο φίλος σου μόλις σου έστειλε ένα μήνυμα με ένα σημαντικό μυστικό. Για να μην μπορούν οι άλλοι να το διαβάσουν εύκολα, το μήνυμα κρυπτογραφήθηκε με μια σειρά χειρισμών bit. Θα χρειαστεί να γράψεις τις συναρτήσεις που θα σε βοηθήσουν να αποκρυπτογραφήσεις το μήνυμα.

1. Μετατόπισε τα bit προς τα πίσω

Το πρώτο βήμα για να αποκρυπτογραφήσεις το μήνυμα είναι να αναιρέσεις τη μετατόπιση της διαδικασίας κρυπτογράφησης, μετατοπίζοντας τα bit πίσω προς τα δεξιά. Στη συνέχεια της διαδικασίας αποκρυπτογράφησης θα υπάρξουν κι άλλα βήματα που υποθέτουν ότι μπαίνουν μηδενικά από την αριστερή πλευρά.

Υλοποίησε τη συνάρτηση shift_back() που παίρνει μια τιμή και τον αριθμό των θέσεων μετατόπισης και εκτελεί τη μετατόπιση.

shift_back(0b1001, 2) # => 0b0010

2. Όρισε μερικά bit

Στη συνέχεια, υπάρχουν μερικά bit που πρέπει να οριστούν σε 1.

Υλοποίησε τη συνάρτηση set_bits() που παίρνει μια τιμή και μια μάσκα και επιστρέφει το αποτέλεσμα του ορισμού των bit της τιμής σε 1. Ένα bit από τη value πρέπει να οριστεί σε 1 όπου το bit της mask είναι επίσης 1. Όλα τα άλλα bit πρέπει να μείνουν αμετάβλητα.

set_bits(0b0110, 0b0101) # => 0b0111

3. Αντιστρέψε συγκεκριμένα bit

Κάποια bit αντιστρέφονται κατά την κρυπτογράφηση. Θα χρειαστεί να αντιστραφούν ξανά για να αποκρυπτογραφηθεί το μήνυμα.

Υλοποίησε τη συνάρτηση flip_bits() που παίρνει μια τιμή και τη μάσκα. Η μάσκα δείχνει ποια bit της τιμής θα αντιστραφούν. Αν το bit είναι 1 στη mask, το bit αντιστρέφεται στη value. Όλα τα άλλα bit μένουν αμετάβλητα.

flip_bits(0b1100, 0b0101) # => 0b1001

4. Μηδένισε συγκεκριμένα bit

Τέλος, υπάρχουν και ορισμένα bit που αποκρυπτογραφούνται πάντα σε 0.

Υλοποίησε τη συνάρτηση clear_bits() που παίρνει μια τιμή και μια μάσκα. Τα bit της value πρέπει να οριστούν σε 0 όπου το bit της μάσκας είναι 1. Όλα τα άλλα bit πρέπει να μείνουν αμετάβλητα.

clear_bits(0b0110, 0b0101) # => 0b0010
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Julia Exercism

Έτοιμος να ξεκινήσεις την άσκηση Μυστικά;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις Julia με 35 έννοιες128 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.