Mật mã IDEA sử dụng phép nhân modulo 2^16 + 1
. Có một thuật toán để thực hiện thao tác này mà không có toán tử modulo chung (chỉ modulo 2^16
(cắt ngắn))? Trong bối cảnh IDEA, số 0 được hiểu là 2^16
(có nghĩa là không phải là đối số của phép nhân của chúng ta và nó không thể là kết quả, vì vậy chúng ta có thể tiết kiệm một chút và lưu trữ giá trị 2^16
làm mẫu bit 0000000000000000
). Tôi tự hỏi làm thế nào để thực hiện nó một cách hiệu quả (hoặc cho dù nó có thể ở tất cả) mà không cần sử dụng các nhà điều hành modulo tiêu chuẩn.Phép nhân nhanh modulo 2^16 + 1
Trả lời
Bạn có thể sử dụng thực tế, rằng (N-1)% N == -1.
Do đó, (65536 * a)% 65.537 == -a% 65537.
Ngoài ra, -a% 65.537 == -a + 1 (mod 65536), khi 0 được hiểu là 65536
uint16_t fastmod65537(uint16_t a, uint16_t b)
{
uint32_t c;
uint16_t hi, lo;
if (a == 0)
return -b + 1;
if (b == 0)
return -a + 1;
c = (uint32_t)a * (uint32_t)b;
hi = c >> 16;
lo = c;
if (lo > hi)
return lo-hi;
return lo-hi+1;
}
vấn đề duy nhất ở đây là nếu hi == lo
, kết quả sẽ là 0. may mắn một bộ kiểm tra xác nhận, rằng nó thực sự không thể ...
int main()
{
uint64_t a, b;
for (a = 1; a <= 65536; a++)
for (b = 1; b <= 65536; b++)
{
uint64_t c = a*b;
uint32_t d = (c % 65537) & 65535;
uint32_t e = m(a & 65535, b & 65535);
if (d != e)
printf("a * b % 65537 != m(%d, %d) real=%d m()=%d\n",
(uint32_t)a, (uint32_t)b, d, e);
}
}
Output: none
ps. Chạy bộ trong lõi i5 đã chứng minh phương pháp% 65537 nhanh hơn. –
Tôi vẫn không hiểu 5 dòng cuối cùng hoạt động như thế nào. Tôi cho rằng nó là chậm hơn vì hai ifs hoặc trình biên dịch đang làm một số phép thuật dưới mui xe. – ciechowoj
Ok, tôi thấy rằng sự thay đổi này chỉ là div và cắt ngắn là mod. – ciechowoj
Thứ nhất, trường hợp a
hoặc b
bằng không. Trong trường hợp đó, nó được xem như là có giá trị 2^16, do đó tiểu học modulo số học cho chúng ta biết:
result = -a - b + 1;
, bởi vì (trong bối cảnh của IDEA) các nghịch đảo của 2^16 vẫn là 2^16, và 16 bit thấp nhất của nó là tất cả các số không.
Các trường hợp chung là dễ dàng hơn nhiều so với có vẻ như, bây giờ mà chúng tôi đã chăm sóc của "0" trường hợp đặc biệt (2^16 + 1 là 0x10001):
/* This operation can overflow: */
unsigned result = (product & 0xFFFF) - (product >> 16);
/* ..so account for cases of overflow: */
result -= result >> 16;
Đưa nó với nhau:
/* All types must be sufficiently wide unsigned, e.g. uint32_t: */
unsigned long long product = a * b;
if (product == 0) {
return -a - b + 1;
} else {
result = (product & 0xFFFF) - (product >> 16);
result -= result >> 16;
return result & 0xFFFF;
}
- 1. Phép nhân và phép trừ nhanh modulo một số nguyên tố
- 2. LAPACK nhanh/BLAS cho phép nhân ma trận
- 3. tính toán modulo nhanh bằng Python và Ruby
- 4. Tối ưu hóa nhân modulo số nguyên tố nhỏ
- 5. Phép nhân trong Python
- 6. Nhân nhanh hơn trong ruby?
- 7. Phép nhân nhân với nửa số hàng chục
- 8. PHP Modulo Decimal
- 9. Tại sao việc cộng và phép nhân nhanh hơn so sánh?
- 10. Cách nhanh nhất để tính toán công suất lớn của 2 modulo là số
- 11. Nhân song song đa GPU cơ bản của phép nhân
- 12. Thực hiện phép chia số nguyên sử dụng phép nhân
- 13. Phép nhân trong lỗi C#
- 14. Python: ghi đè phép nhân
- 15. Vectorize phép nhân NumPy lớn
- 16. Điểm nổi; Phân chia vs Phép nhân
- 17. Phép nhân ma trận song song
- 18. Tối ưu hóa phép nhân .NET
- 19. Phép nhân ma trận chuỗi ma trận
- 20. ma trận phép nhân trong core.matrix
- 21. Phép nhân Spark Matrix với python
- 22. Phép nhân song song OpenMP bằng phép nhân ba cho vòng lặp (vấn đề hiệu suất)
- 23. Sự tồn tại của phép cộng/phép nhân trong ruby?
- 24. Nhân nhanh các số nguyên rất lớn
- 25. Phép nhân ma trận trong hadoop
- 26. Phép nhân ma trận trong GSL-GNU
- 27. Thư viện phép nhân hàng chục
- 28. Thực hiện phép nhân trong SQL
- 29. Phép nhân cho kết quả gần đúng
- 30. Phép nhân ma trận sử dụng CUDA
Tôi đã thêm một số làm rõ. – ciechowoj