Điều này đúng với tất cả các số âm.
f (n) = abs (n)
Bởi vì có một số âm nhiều hơn số dương cho các số nguyên bổ sung twos, nên f(n) = abs(n)
có giá trị cho một trường hợp nhiều hơn so với f(n) = n > 0 ? -n : n
giải pháp giống như f(n) = -abs(n)
. Có bạn bởi một ...: D
CẬP NHẬT
Không, nó không hợp lệ cho một trường hợp nữa vì tôi vừa nhận ra bằng nhận xét của litb ... abs(Int.Min)
sẽ chỉ tràn ...
Tôi cũng nghĩ về việc sử dụng thông tin mod 2, nhưng kết luận, nó không hoạt động ... sớm. Nếu được thực hiện đúng, nó sẽ hoạt động cho tất cả các số trừ Int.Min
vì điều này sẽ tràn.
CẬP NHẬT
Tôi đã chơi với nó một lúc, tìm kiếm một mẹo thao tác bit đẹp, nhưng tôi không thể tìm thấy một lớp lót đẹp, trong khi giải pháp mod 2 phù hợp với một.
f (n) = 2n (abs (n)% 2) - n + sgn (n)
Trong C #, điều này trở thành như sau:
public static Int32 f(Int32 n)
{
return 2 * n * (Math.Abs(n) % 2) - n + Math.Sign(n);
}
Để làm cho nó làm việc cho tất cả các giá trị, bạn phải thay thế Math.Abs()
với (n > 0) ? +n : -n
và bao gồm việc tính toán trong một unchecked
khối. Sau đó, bạn thậm chí Int.Min
được ánh xạ tới chính nó như phủ định không được kiểm soát.
CẬP NHẬT
Lấy cảm hứng từ một câu trả lời khác tôi sẽ giải thích cách thức hoạt động của chức năng và cách xây dựng một chức năng như vậy.
Hãy bắt đầu ngay từ đầu. Hàm f
này được lặp đi lặp lại cho một giá trị nhất định n
mang lại một chuỗi các giá trị.
n => f (n) => f (f (n)) => f (f (f (n))) => f (f (f (f (n)))) => ...
Câu hỏi đòi hỏi f(f(n)) = -n
, đó là hai ứng dụng liên tiếp f
phủ định lập luận. Hai ứng dụng nữa của f
- tổng cộng bốn - phủ nhận lại lập luận một n
lần nữa.
n => f (n) => -n => f (f (f (n))) => n => f (n) => ...
Bây giờ có một chu kỳ rõ ràng của chiều dài bốn. Thay thế x = f(n)
và lưu ý rằng phương trình thu được f(f(f(n))) = f(f(x)) = -x
giữ, mang lại kết quả như sau.
n => x => -n => -x => n => ...
Vì vậy, chúng ta có được một chu kỳ có độ dài bốn với hai số và hai số bị phủ định. Nếu bạn tưởng tượng chu trình là một hình chữ nhật, các giá trị phủ định được đặt ở các góc đối diện.
Một trong nhiều giải pháp để xây dựng một chu trình như vậy là sau đây bắt đầu từ n.
n => phủ định và trừ đi một
-n - 1 = - (n + 1) => thêm một
-n => phủ nhận và thêm một
n + 1 => trừ đi một
n
Một ví dụ cụ thể là của một chu kỳ như vậy +1 => -2 => -1 => +2 => +1
. Chúng ta đang gần hoàn tất. Lưu ý rằng chu trình được xây dựng chứa một số dương lẻ, kế tiếp của nó và cả hai số đều phủ định, chúng ta có thể dễ dàng phân chia các số nguyên thành nhiều chu kỳ như vậy ( 2^32
là bội số của bốn) và đã tìm thấy một hàm thỏa mãn các điều kiện.
Nhưng chúng tôi có một vấn đề với số không. Chu trình phải chứa 0 => x => 0
bởi vì số 0 được phủ định cho chính nó. Và bởi vì các trạng thái chu kỳ đã 0 => x
theo sau nó 0 => x => 0 => x
. Đây chỉ là một chu kỳ có độ dài hai và x
được biến thành chính nó sau hai ứng dụng, không phải vào -x
. May mắn thay, có một trường hợp giải quyết vấn đề. Nếu X
bằng 0, chúng ta có được một chu kỳ có độ dài chỉ bằng 0 và chúng ta đã giải quyết vấn đề đó kết luận rằng số 0 là một điểm cố định f
.
Làm xong? Hầu hết. Chúng ta có các 2^32
số, số 0 là một điểm cố định để lại các 2^32 - 1
số và chúng ta phải phân chia số đó thành các chu kỳ gồm bốn số. Xấu 2^32 - 1
không phải là bội số của bốn - sẽ vẫn còn ba số không thuộc bất kỳ chu kỳ nào có độ dài bốn.
Tôi sẽ giải thích phần còn lại của giải pháp bằng cách sử dụng tập hợp nhỏ hơn 3 bit có chữ ký khác nhau từ -4
đến +3
. Chúng tôi được thực hiện với số không. Chúng tôi có một chu kỳ hoàn chỉnh +1 => -2 => -1 => +2 => +1
. Bây giờ hãy để chúng tôi xây dựng chu kỳ bắt đầu từ +3
.
+3 => -4 => -3 => +4 => +3
Vấn đề phát sinh +4
là không thể biểu diễn dưới dạng số nguyên 3 bit. Chúng tôi sẽ có được +4
bằng cách phủ nhận -3
đến +3
- những gì vẫn còn là một chút 3 số nguyên hợp lệ - nhưng sau đó thêm một đến +3
(nhị phân 011
) mang 100
nhị phân. Được hiểu là số nguyên không dấu +4
nhưng chúng ta phải hiểu nó là số nguyên đã ký -4
. Vì vậy, thực sự -4
cho ví dụ này hoặc Int.MinValue
trong trường hợp chung là một điểm cố định thứ hai của phủ định số học số nguyên - 0
và Int.MinValue
được ánh xạ tới themselve. Vì vậy, chu kỳ thực sự là như sau.
+3 => -4 => -3 => -4 => -3
Đó là một chu kỳ có độ dài hai và thêm +3
vào chu kỳ thông qua -4
. Do đó, -4
ánh xạ chính xác đến chính nó sau hai ứng dụng chức năng, +3
được ánh xạ chính xác đến -3
sau hai ứng dụng chức năng, nhưng -3
được ánh xạ nhầm sang chính nó sau hai ứng dụng chức năng.
Vì vậy, chúng tôi đã xây dựng một hàm hoạt động cho tất cả các số nguyên trừ một số nguyên. Chúng ta có thể làm tốt hơn không? Không chúng tôi không thể. Tại sao? Chúng ta phải xây dựng các chu kỳ có độ dài bốn và có thể bao phủ toàn bộ phạm vi số nguyên lên đến bốn giá trị. Các giá trị còn lại là hai điểm cố định 0
và Int.MinValue
phải được ánh xạ tới chính chúng và hai số nguyên tùy ý x
và -x
phải được ánh xạ với nhau bởi hai ứng dụng chức năng.
Để ánh xạ x
tới -x
và ngược lại, chúng phải tạo thành một chu kỳ bốn và chúng phải được đặt ở các góc đối diện của chu kỳ đó. Trong hậu quả 0
và Int.MinValue
phải ở các góc đối diện, quá. Điều này sẽ ánh xạ chính xác x
và -x
nhưng trao đổi hai điểm cố định 0
và Int.MinValue
sau hai ứng dụng chức năng và để lại cho chúng tôi hai đầu vào không thành công. Vì vậy, không thể xây dựng một hàm hoạt động cho tất cả các giá trị, nhưng chúng ta có một hàm hoạt động cho tất cả các giá trị ngoại trừ một giá trị và đây là cách tốt nhất chúng ta có thể đạt được.