C bổ sung bằng cách sử dụng mô-đun


81

Tôi đã xem qua một đoạn mã C hấp dẫn có thể in ra A + B, nhưng tôi khó hiểu nó.

Định dạng đầu vào:

A B

trong đó A, Blà các số nguyên nằm giữa 0và được 10phân tách bằng một khoảng trắng.

Mã:

main( n )
{
    gets( &n );
    printf("%d", n % 85 - 43);
}

Điều này nhằm mục đích viết mã ngắn, xin đừng bận tâm đến những cảnh báo.

Những gì tôi hiểu cho đến nay:

gets( &n )lưu trữ các giá trị ASCII của A, khoảng trắng và B trong ba byte dưới của n. Ví dụ, A = 3B = 8sẽ mang lại n = 0x00382033. Điều kiện đưa ra ngăn không cho ntràn. Nhưng tôi không hiểu thế nào là n % 85 - 43sản lượng A + B.

Làm thế nào để bạn đưa ra những con số này?


2
Thực sự hấp dẫn.
Havenard

12
Một gợi ý là 85 là các bit xen kẽ trong hệ nhị phân , 01010101. Nếu bạn thử cách tiếp cận này với 10101010, đó là số 170, bạn sẽ có chức năng tương tự, sự khác biệt duy nhất là nếu bạn làm với 0 0bạn sẽ nhận được số 128 thay thế ( 10000000ở dạng nhị phân). Một kỹ thuật tương tự được sử dụng để thực hiện một loạt các tối ưu hóa với các phép toán bit chẳng hạn như đếm số bit trong một tập hợp bit bằng cách sử dụng các mặt nạ như 0x555555550xAAAAAAAA(0x55 = 85 và 0xAA = 170). Nếu bạn google những mã thập lục phân đó, bạn sẽ nhận được một loạt các bài báo thú vị.
Havenard

Chà, tôi chưa bao giờ mong đợi độ sâu như thế này ở con số 85. Cảm ơn vì sự hiểu biết sâu sắc.
William Lee,

1
Tôi giả sử bạn có nghĩa là từ 0 đến 9 bao gồm?
pipe,

1
Đó chắc chắn là ioccc xứng đáng.
dgnuff 19/07/18

Câu trả lời:


87

Với các int ít endian (và giả sử văn bản ASCII và byte 8 bit, và tất cả các giả định khác mà mã yêu cầu) và bỏ qua tất cả các nội dung C sai về mặt kỹ thuật trong mã, "Điều tôi hiểu cho đến nay ”là chính xác.

gets(&n)sẽ lưu trữ các giá trị ASCII của A, khoảng trắng và B vào 3 byte đầu tiên của n. Nó cũng sẽ lưu trữ một dấu chấm hết null vào byte thứ 4. Lưu trữ những giá trị ASCII vào những byte nkết quả trong nlấy giá trị B*256*256 + space*256 + A, nơi B, spaceAđại diện cho các giá trị ASCII tương ứng.

256 mod 85 là 1, do đó theo các thuộc tính của số học mô-đun,

(B*256*256 + space*256 + A) % 85 = (B + space + A) % 85

Ngẫu nhiên, với ints big-endian 4 byte, chúng tôi nhận được

(A*256*256*256 + space*256*256 + B*256) % 85 = (B + space + A) % 85

vì vậy sự bền vững không quan trọng, miễn là chúng ta có ints 4 byte. (Các số nguyên lớn hơn hoặc nhỏ hơn có thể là một vấn đề; ví dụ: với các số nguyên 8 byte, chúng tôi sẽ phải lo lắng về những gì trong số byte nđó getskhông được đặt.)

Khoảng trắng là ASCII 32 và giá trị ASCII cho một ký tự chữ số là 48 + giá trị của chữ số. Xác định abnhư các giá trị số của các chữ số vào (chứ không phải là giá trị ASCII của ký tự chữ số), chúng tôi có

(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

trong đó hai giá trị tương đương cuối cùng dựa vào thực tế abnhận các giá trị từ 0 đến 9.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.