Natrafiłem na intrygujący kod C, który drukuje A + B
, ale mam problem ze zrozumieniem.
Format wejściowy:
A B
gdzie A
, B
liczby całkowite od 0
i 10
oddzielone przez jedną przestrzeń.
Kod:
main( n )
{
gets( &n );
printf("%d", n % 85 - 43);
}
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 = 3
i B = 8
ustąpi n = 0x00382033
. Podane warunki zapobiegają n
przepełnieniu. Ale nie rozumiem, jak n % 85 - 43
plony A + B
.
Jak wymyślasz te liczby?
01010101
. Jeśli spróbujesz tego podejścia z10101010
liczbą 170, uzyskasz podobną funkcjonalność, jedyną różnicą jest to, że jeśli zrobisz z0 0
, zamiast tego otrzymasz liczbę 128 (która jest10000000
binarna). 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 jak0x55555555
i0xAAAAAAAA
(0x55 = 85 i 0xAA = 170). Jeśli wygooglujesz te szesnastkowe kody, otrzymasz kilka interesujących artykułów.Odpowiedzi:
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 bajtachn
. Przechowuje również terminator zerowy w czwartym bajcie. Przechowywanie tych wartości ASCII do tych bajtówn
powodujen
przyjmując wartośćB*256*256 + space*256 + A
, gdzieB
,space
iA
reprezentują odpowiednie wartości ASCII.256 mod 85 to 1, a więc przez właściwości arytmetyki modularnej,
(B*256*256 + space*256 + A) % 85 = (B + space + A) % 85
Nawiasem mówiąc, z 4-bajtowymi intami typu big-endian otrzymujemy
(A*256*256*256 + space*256*256 + B*256) % 85 = (B + space + A) % 85
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,
n
któregets
nie zostały ustawione).Spacja to ASCII 32, a wartość ASCII dla znaku cyfry to 48 + wartość cyfry. Definiując
a
ib
jako wartości liczbowe wprowadzanych cyfr (zamiast wartości ASCII znaków cyfr), mamy(B + space + A) % 85 = (b + 48 + 32 + a + 48) % 85 = (a + b + 128) % 85 = (a + b + 43) % 85 (B + space + A) % 85 - 43 = (a + b + 43) % 85 - 43 = (a + b) % 85 = a + b
gdzie ostatnie dwa odpowiedniki polegają na tym, że
a
ib
przyjmują wartości od 0 do 9.źródło