Ngoài thực tế là hàm băm của bạn không phải là một hàm quá tốt * , vấn đề lớn nhất với mã của bạn không phải là nó trả về một số khác tùy thuộc vào phiên bản .NET, mà là trong cả hai trường hợp, nó trả về một số hoàn toàn vô nghĩa: câu trả lời chính xác cho vấn đề là
49 103 mod 143 = là 114. ( liên kết tới Wolfram Alpha )
Bạn có thể sử dụng mã này để tính toán câu trả lời này:
private static int PowMod(int a, int b, int mod) {
if (b == 0) {
return 1;
}
var tmp = PowMod(a, b/2, mod);
tmp *= tmp;
if (b%2 != 0) {
tmp *= a;
}
return tmp%mod;
}
Lý do tại sao phép tính của bạn tạo ra một kết quả khác là để tạo ra một câu trả lời, bạn sử dụng một giá trị trung gian làm giảm hầu hết các chữ số có nghĩa của số 49 103 : chỉ 16 chữ số đầu tiên trong số 175 chữ số của nó là đúng!
1230824813134842807283798520430636310264067713738977819859474030746648511411697029659004340261471771152928833391663821316264359104254030819694748088798262075483562075061997649
159 chữ số còn lại đều sai. Tuy nhiên, hoạt động mod tìm kiếm một kết quả yêu cầu mọi chữ số đều phải đúng, kể cả những chữ số cuối cùng. Do đó, ngay cả những cải tiến nhỏ nhất về độ chính xác Math.Pow
có thể đã được thực hiện trong .NET 4, sẽ dẫn đến sự khác biệt lớn trong phép tính của bạn, về cơ bản tạo ra một kết quả tùy ý.
* Vì câu hỏi này nói về việc nâng số nguyên lên lũy thừa cao trong bối cảnh băm mật khẩu, nên đọc liên kết câu trả lời này trước khi quyết định xem có nên thay đổi cách tiếp cận hiện tại của bạn để có khả năng tốt hơn hay không.