为什么这个Szudzik典雅配对会给出错误的结果?

时间:2019-11-25 15:27:53

标签: java algorithm function math equation

我正在使用优雅的配对将两个数字配对以形成一个唯一的数字。但是,当我将67108863上方的两个相同数字配对时,例如“ pair(67108864,67108864)”,它将给我4503599761588224。当我想将其取消配对时,它将给我(-1,67108865)。然后,我尝试配对(-1,67108865),它也给了我4503599761588224。所有其他不同的数字在67108864下给出一个唯一的数字或相同的数字,除非我在67108863以上对相同的数字进行配对,否则我可以配对和取消配对。 (67108864,67108864),(507108864,507108864)等。

我的代码中是否有错误或者我刚发现Szudzik典雅配对功能存在问题?

/**
 *
 * @author HiltherJoe
 */
public class ElegantP {
    public static long pair(long x, long y) {
        return x >= y ? x * x + x + y : y * y + x;
    }
    public static long[] unpair(long z) {
        long b = (long) Math.sqrt(z);
        long a = z - b * b;
        return a < b ? new long[]{a, b} : new long[]{b, a - b};
    }
    public static void main(String[] args){
        int i = 67108864;
        long pairedNumber = pair(i, i);
        long[] unpair = unpair(pairedNumber);
        System.out.println("Paired Number is    " + pairedNumber);
        System.out.println("First unpaired Number is    " + unpair[0]+"    Second unpaired Number is    "+unpair[1]);
    }
}

1 个答案:

答案 0 :(得分:2)

此代码使用Math.sqrt()进行double计算-结果不够精确。对于4503599761588224pair(67108864,67108864)),它是67108865而不是67108864

使用BigInteger.sqrt()(或任何其他精确方法),它应该可以工作:

long b = BigInteger.valueOf(z).sqrt().longValue();
long a = z - b * b;

对于更大的数字,仍然存在SMA的commented溢出风险