ฟังก์ชั่นการจับคู่ต้นเสียงมันเป็นหนึ่งในคนที่ดีกว่าออกมีการพิจารณาที่เรียบง่ายรวดเร็วและพื้นที่ที่มีประสิทธิภาพ แต่มีบางสิ่งที่ดียิ่งขึ้นเผยแพร่ในวุลแฟรมโดยแมทธิว Szudzik นี่ ข้อ จำกัด ของฟังก์ชั่นการจับคู่คันทอร์ (ค่อนข้าง) คือช่วงของผลลัพธ์ที่เข้ารหัสไม่ได้อยู่ภายในขีด จำกัด ของ2N
จำนวนเต็มบิตเสมอถ้าอินพุตเป็นN
จำนวนเต็มสองบิต นั่นคือถ้าอินพุตของฉันเป็น16
จำนวนเต็มสองบิตตั้งแต่0 to 2^16 -1
นั้นจะมีการ2^16 * (2^16 -1)
รวมกันของอินพุตดังนั้นด้วยหลักการ Pigeonhole ที่ชัดเจนเราต้องการเอาต์พุตขนาดอย่างน้อย2^16 * (2^16 -1)
ซึ่งเท่ากับ2^32 - 2^16
หรือในคำอื่น ๆ แผนที่ของ32
ตัวเลขบิตควรเป็นไปได้อย่างดีเลิศ สิ่งนี้อาจไม่ได้มีความสำคัญในทางปฏิบัติเพียงเล็กน้อยในโลกแห่งการเขียนโปรแกรม
ฟังก์ชั่นการจับคู่คันทอร์ :
(a + b) * (a + b + 1) / 2 + a; where a, b >= 0
การแมปสำหรับจำนวนเต็ม 16 บิตสูงสุดสองบิต (65535, 65535) จะเป็น 8589803520 ซึ่งตามที่คุณเห็นไม่สามารถใส่ลงใน 32 บิตได้
เข้าสู่ฟังก์ชั่นของ Szudzik :
a >= b ? a * a + a + b : a + b * b; where a, b >= 0
การแมปสำหรับ (65535, 65535) จะเป็น 4294967295 ซึ่งตามที่คุณเห็นคือจำนวนเต็ม 32 บิต (0 ถึง 2 ^ 32 -1) นี่คือจุดที่โซลูชั่นนี้เหมาะอย่างยิ่งมันใช้ประโยชน์ทุกจุดในพื้นที่นั้นเท่านั้นดังนั้นจึงไม่มีสิ่งใดสามารถทำให้พื้นที่มีประสิทธิภาพมากขึ้นได้
ตอนนี้เมื่อพิจารณาถึงความจริงที่ว่าเรามักจะจัดการกับการติดตั้งใช้งานที่มีการลงนามของจำนวนขนาดต่าง ๆ ในภาษา / กรอบงานให้พิจารณาsigned 16
จำนวนบิตบิตตั้งแต่-(2^15) to 2^15 -1
(ต่อมาเราจะเห็นวิธีการขยายแม้ ouput ตั้งแต่a
และจะต้องมีการบวกที่พวกเขามีตั้งแต่b
0 to 2^15 - 1
ฟังก์ชั่นการจับคู่คันทอร์ :
การแมปสำหรับจำนวนเต็มสูงสุด 16 บิตที่ลงนามมากที่สุดสอง (32767, 32767) จะเป็น 2147418112 ซึ่งเป็นเพียงสั้น ๆ ของค่าสูงสุดสำหรับจำนวนเต็ม 32 บิตลงนาม
ตอนนี้ฟังก์ชั่นของ Szudzik :
(32767, 32767) => 1073741823 มีขนาดเล็กลง ..
ลองบัญชีจำนวนเต็มลบ นี่เป็นคำถามที่นอกเหนือไปจากคำถามเดิมที่ฉันรู้ แต่เพียงอธิบายอย่างละเอียดเพื่อช่วยผู้เข้าชมในอนาคต
ฟังก์ชั่นการจับคู่คันทอร์ :
A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
(A + B) * (A + B + 1) / 2 + A;
(-32768, -32768) => 8589803520 ซึ่งเป็น Int64 เอาต์พุต 64 บิตสำหรับอินพุต 16 บิตอาจยกโทษให้ไม่ได้ !!
ฟังก์ชั่นของ Szudzik :
A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
A >= B ? A * A + A + B : A + B * B;
(-32768, -32768) => 4294967295 ซึ่งเป็น 32 บิตสำหรับช่วงที่ไม่ได้ลงชื่อหรือ 64 บิตสำหรับช่วงที่ลงนาม แต่ยังดีกว่า
ตอนนี้ทั้งหมดในขณะที่การส่งออกเป็นบวกเสมอ ในโลกลงนามมันจะประหยัดพื้นที่มากยิ่งขึ้นถ้าเราสามารถถ่ายโอนครึ่งหนึ่งออกไปยังแกนเชิงลบ คุณสามารถทำได้เช่นนี้สำหรับ Szudzik's:
A = a >= 0 ? 2 * a : -2 * a - 1;
B = b >= 0 ? 2 * b : -2 * b - 1;
C = (A >= B ? A * A + A + B : A + B * B) / 2;
a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
(-32768, 32767) => -2147483648
(32767, -32768) => -2147450880
(0, 0) => 0
(32767, 32767) => 2147418112
(-32768, -32768) => 2147483647
สิ่งที่ฉันทำ: หลังจากใช้น้ำหนักของ2
ปัจจัยการผลิตและจะผ่านฟังก์ชั่นที่ผมแล้วแบ่ง ouput -1
โดยสองคนและใช้บางส่วนของพวกเขากับแกนเชิงลบโดยคูณด้วย
ดูผลลัพธ์สำหรับอินพุตใด ๆ ในช่วงของ16
หมายเลขบิตที่เซ็นชื่อเอาต์พุตอยู่ภายในขีด จำกัด ของ32
เลขจำนวนบิตบิตที่เซ็นชื่อซึ่งเท่ ฉันไม่แน่ใจว่าจะทำอย่างไรในลักษณะเดียวกันสำหรับฟังก์ชั่นการจับคู่คันทอร์ แต่ไม่ได้พยายามเท่าที่มีประสิทธิภาพ ยิ่งไปกว่านั้นการคำนวณที่เกี่ยวข้องกับฟังก์ชั่นการจับคู่คันทอร์ก็ยิ่งช้าลงเช่นกัน
นี่คือการใช้ C #
public static long PerfectlyHashThem(int a, int b)
{
var A = (ulong)(a >= 0 ? 2 * (long)a : -2 * (long)a - 1);
var B = (ulong)(b >= 0 ? 2 * (long)b : -2 * (long)b - 1);
var C = (long)((A >= B ? A * A + A + B : A + B * B) / 2);
return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}
public static int PerfectlyHashThem(short a, short b)
{
var A = (uint)(a >= 0 ? 2 * a : -2 * a - 1);
var B = (uint)(b >= 0 ? 2 * b : -2 * b - 1);
var C = (int)((A >= B ? A * A + A + B : A + B * B) / 2);
return a < 0 && b < 0 || a >= 0 && b >= 0 ? C : -C - 1;
}
เนื่องจากการคำนวณระดับกลางสามารถเกินขีด จำกัด ของ2N
จำนวนเต็มที่ลงนามแล้วฉันจึงใช้4N
ประเภทจำนวนเต็ม (การหารสุดท้ายโดย2
นำผลลัพธ์กลับมา2N
)
ลิงก์ที่ฉันให้ไว้ในโซลูชันทางเลือกแสดงกราฟของฟังก์ชันที่ใช้ทุกจุดในอวกาศอย่างชัดเจน มันวิเศษมากที่เห็นว่าคุณสามารถเข้ารหัสคู่ของพิกัดเป็นตัวเลขเดียวกลับด้านได้! โลกมหัศจรรย์ของตัวเลข !!