Dodawanie C za pomocą modułu

81

Natrafiłem na intrygujący kod C, który drukuje A + B, ale mam problem ze zrozumieniem.

Format wejściowy:

gdzie A, Bliczby całkowite od 0i 10oddzielone przez jedną przestrzeń.

Kod:

To było przeznaczone do krótkiego kodowania, proszę nie przejmować się ostrzeżeniami.

Co rozumiem do tej pory:

gets( &n )przechowuje wartości ASCII A, spacji i B w trzech niższych bajtach n. Na przykład A = 3i B = 8ustąpi n = 0x00382033. Podane warunki zapobiegają nprzepełnieniu. Ale nie rozumiem, jak n % 85 - 43plony A + B.

Jak wymyślasz te liczby?

Williama Lee
źródło
2
Doprawdy intrygujące.
Havenard,
12
Podpowiedź jest to, że 85 bitów jest przemienne binarnie 01010101. Jeśli spróbujesz tego podejścia z 10101010liczbą 170, uzyskasz podobną funkcjonalność, jedyną różnicą jest to, że jeśli zrobisz z 0 0, zamiast tego otrzymasz liczbę 128 (która jest 10000000binarna). Podobna technika jest używana do wykonywania wielu optymalizacji z operacjami bitowymi, takimi jak zliczanie liczby bitów w zestawie bitów za pomocą masek, takich jak 0x55555555i 0xAAAAAAAA(0x55 = 85 i 0xAA = 170). Jeśli wygooglujesz te szesnastkowe kody, otrzymasz kilka interesujących artykułów.
Havenard,
Wow, nigdy nie spodziewałem się tak dużej głębokości w liczbie 85. Dzięki za wgląd.
William Lee,
1
Zakładam, że masz na myśli od 0 do 9 włącznie?
fajka
1
To zdecydowanie warte IOCCC .
dgnuff

Odpowiedzi:

87

Z little-endian ints (i zakładając tekst ASCII i 8-bitowe bajty oraz wszystkie inne założenia, których wymaga kod) i ignorując wszystkie technicznie błędne elementy w nowoczesnym C w kodzie, twoje „Co rozumiem jak dotąd ”jest poprawne.

gets(&n)zapisze wartości ASCII A, spacji i B w pierwszych 3 bajtach n. Przechowuje również terminator zerowy w czwartym bajcie. Przechowywanie tych wartości ASCII do tych bajtów npowoduje nprzyjmując wartość B*256*256 + space*256 + A, gdzie B, spacei Areprezentują odpowiednie wartości ASCII.

256 mod 85 to 1, a więc przez właściwości arytmetyki modularnej,

Nawiasem mówiąc, z 4-bajtowymi intami typu big-endian otrzymujemy

więc endianness nie ma znaczenia, o ile mamy 4-bajtowe liczby int. (Większe lub mniejsze wartości mogą stanowić problem; na przykład przy 8-bajtowych intach musielibyśmy się martwić o to, co jest w bajtach, nktóre getsnie zostały ustawione).

Spacja to ASCII 32, a wartość ASCII dla znaku cyfry to 48 + wartość cyfry. Definiując ai bjako wartości liczbowe wprowadzanych cyfr (zamiast wartości ASCII znaków cyfr), mamy

gdzie ostatnie dwa odpowiedniki polegają na tym, że ai bprzyjmują wartości od 0 do 9.

user2357112 obsługuje Monikę
źródło