【问题标题】:Why is this Szudzik Elegant Pairing giving wrong result?为什么这个 Szudzik 优雅配对会给出错误的结果?
【发布时间】:2019-11-25 15:27:53
【问题描述】:

我正在使用优雅的配对将两个数字配对以形成一个唯一的数字。但是当我配对两个高于 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]);
    }
}

【问题讨论】:

  • 这是由于溢出。 Long 有一个范围值,您通过取值的平方来突破该范围值。
  • @SMA 我不认为这是一个溢出问题,因为更大的数字可以工作并返回原始数字。尝试其他大于 67108864 的不同数字,你会看到你会得到这些数字。另外,为什么它适用于 67108863 而不是 67108864?

标签: java algorithm function math equation


【解决方案1】:

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

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

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

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

【讨论】:

  • 溢出确实如此,如果数字更大,我只使用 BigInteger
猜你喜欢
  • 2011-09-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-05-21
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多