检查长整数是否为多维数据集的快速方法(在Java中)
我正在编写一个程序,其中要求我检查某些大数(立方体的排列)是否是立方的(对于某些n,等于n^3) 目前我只是简单地使用这个方法检查长整数是否为多维数据集的快速方法(在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个多维数据
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;
}