Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/entity-framework/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
检查长整数是否为多维数据集的快速方法(在Java中)_Java_Algorithm_Math_Numbers_Cubes - Fatal编程技术网

检查长整数是否为多维数据集的快速方法(在Java中)

检查长整数是否为多维数据集的快速方法(在Java中),java,algorithm,math,numbers,cubes,Java,Algorithm,Math,Numbers,Cubes,我正在编写一个程序,其中要求我检查某些大数(立方体的排列)是否是立方的(对于某些n,等于n^3) 目前我只是简单地使用这个方法 static boolean isCube(long input) { double cubeRoot = Math.pow(input,1.0/3.0); return Math.round(cubeRoot) == cubeRoot; } 但在处理大数字(10+位数)时,速度非常慢。有没有更快的方法来确定整数是否为多维数据集?只有2^21个多维数据

我正在编写一个程序,其中要求我检查某些大数(立方体的排列)是否是立方的(对于某些n,等于n^3)

目前我只是简单地使用这个方法

static boolean isCube(long input) {
    double cubeRoot = Math.pow(input,1.0/3.0);
    return Math.round(cubeRoot) == cubeRoot;
}

但在处理大数字(10+位数)时,速度非常慢。有没有更快的方法来确定整数是否为多维数据集?

只有2^21个多维数据集不会溢出长数据集(如果允许负数,则为2^22-1),因此您可以使用哈希集查找。

请定义非常大的显示。下面是一个测试程序:

public static void main(String[] args) {
    for (long v = 1; v > 0; v = v * 10) {
        long start = System.nanoTime();
        for (int i = 0; i < 100; i++)
            isCube(v);
        long end = System.nanoTime();
        System.out.println(v + ": " + (end - start) + "ns");
    }
}
static boolean isCube(long input) {
    double cubeRoot = Math.pow(input,1.0/3.0);
    return Math.round(cubeRoot) == cubeRoot;
}

我看不到“大”数字对性能的影响。

您可以先通过测试给定数字的模来消除大量候选数字。例如,对数字进行模化的多维数据集
819
只能具有以下
45

 0  125  181  818  720  811  532  755  476
 1  216   90  307  377  694  350  567  442
 8  343  559  629  658  351  190   91  469
27  512  287  252  638  118  603  161  441
64  729   99  701  792  378  260  468  728
因此,在几乎95%的均匀分布情况下,您可以不必实际计算立方根。

这本书有一个用于整数立方根的短而快的函数,值得移植到64位长度,见下文


似乎测试一个数字是否是一个完美的立方体比实际计算立方根要快。它使用了“”(求和数字。重复,直到它是一个数字)。如果数字根为0、1或8,则数字可能是一个完美的立方体

这种方法对于排列(数字的?)数字非常有价值。如果您可以通过数字根排除一个数字,那么也将排除所有排列

他们还描述了一种基于基本因子的检查完美立方体的技术。这看起来最适合心算,因为我认为因子分解比在计算机上生成多维数据集要慢

无论如何,数字根对计算机来说很快,你甚至可以用数字串作为开始。您仍然需要一个除以10的循环,但是您的起点是输入的数字之和,而不是整数,因此它不会有很多个除法。(整数除法比当前CPU上的乘法要慢一个数量级,但用编译时常数除法也可以。希望Java JIT编译器也能使用整数除法,甚至可以将其用于运行时常数。)

这个加号(
input%819
->搜索一个包含45个条目的表)将排除许多输入,因为它们不可能是完美的立方体。 IDK,如果二进制搜索、线性搜索或哈希/集是最好的

这些测试可能只是将
long
s集存储在数据结构中的前端,这些数据结构是完美的多维数据集,允许快速检查是否存在。(例如)。是的,缓存未命中非常昂贵,至少在进行哈希集查找之前,数字根测试可能是值得的,可能两者都是

通过将其用于一个而不是一个精确的集合(),您可以在这个想法上使用更少的内存。这将为整个计算提供另一个候选拒绝前端。需要一个“漏斗”函数将对象转换为字节,在本例中,字节应为f(x)=x)

我怀疑Bloom过滤不会比精确的HashSet检查有多大的优势,因为它需要多个内存访问。当你真的负担不起一个满表的空间,并且你过滤掉的东西非常昂贵,比如磁盘访问时,这是合适的

整数立方根函数(如下)可能比单个缓存未命中更快。如果cbrt检查导致缓存未命中,那么当其数据被逐出时,代码的其余部分可能也会遭受更多的缓存未命中


Math.SE有一个,但那是关于正方形的,不是立方体的,所以这些都没有出现。不过,那里的答案确实讨论并避免了您方法中的问题

长转换可能是瓶颈的主要部分

事实上,我很好奇。事实证明,在(use/copying/distribution.AFAICT,本质上是公共域代码)中已经有一个整数多维数据集根实现:

//黑客的喜悦整数立方根(我想是32位整数)
int icbrt1(无符号x){
int-s;
无符号y,b;
y=0;
法罗群岛
 0  125  181  818  720  811  532  755  476
 1  216   90  307  377  694  350  567  442
 8  343  559  629  658  351  190   91  469
27  512  287  252  638  118  603  161  441
64  729   99  701  792  378  260  468  728
static boolean isCube(long input) {
    double cubeRoot = Math.cbrt(input);
    long intRoot = Math.round(cubeRoot);
    return (intRoot*intRoot*intRoot) == input;
}
// Hacker's delight integer cube-root (for 32-bit integers, I think)
int icbrt1(unsigned x) {
   int s;
   unsigned y, b;

   y = 0;
   for (s = 30; s >= 0; s = s - 3) {
      y = 2*y;
      b = (3*y*(y + 1) + 1) << s;
      if (x >= b) {
         x = x - b;
         y = y + 1;
      }
   }
   return y;
}
private static int cubeRoot(long n) {
    final int MAX_POWER = 21;
    int power = MAX_POWER;
    long factor;
    long root = 0;
    long next, square, cube;

    while (power >= 0) {
        factor = 1 << power;
        next = root + factor;
        while (true) {
            if (next > n) {
                break;
            }
            if (n / next < next) {
                break;
            }
            square = next * next;
            if (n / square < next) {
                break;
            }
            cube = square * next;
            if (cube > n) {
                break;
            }
            root = next;
            next += factor;
        }
        --power;
    }
    return (int) root;
}