我正在玩Emscripten,并编译了一些简单的程序来测试其性能。这是我快速组合在一起的fib(n)
算法。实施并不重要,但是如果需要的话,这里是来源:
#include <stdlib.h>
#include <stdio.h>
#define KEY_TYPE unsigned int
#define VALUE_TYPE unsigned long long
// Simple linked list implementation
typedef struct list{
KEY_TYPE key;
VALUE_TYPE value;
struct list* next;
} list;
void free_list(list** headPtr){
list* head = *headPtr;
while(head){
list* next = head->next;
free(head);
head = next;
}
}
VALUE_TYPE lookup_list(list** headPtr, KEY_TYPE key){
for(list* head = *headPtr; head; head = head->next){
if(head->key == key){
return head->value;
}
}
return 0;
}
void add_list(list** headPtr, list* block){
block->next = *headPtr;
*headPtr = block;
}
VALUE_TYPE fib_recur(list** lookup, KEY_TYPE n){
VALUE_TYPE value;
// base cases
if(n < 2) return n;
// look for cached answer
value = lookup_list(lookup, n);
if(value > 0) return value;
// calculate answer
value = fib_recur(lookup, n - 1) + fib_recur(lookup, n - 2);
list* head = calloc(sizeof(list), 1);
head->key = n;
head->value = value;
add_list(lookup, head);
return value;
}
VALUE_TYPE fib(n){
list* listPtr = NULL;
VALUE_TYPE num = fib_recur(&listPtr, n);
free_list(&listPtr);
return num;
}
int main(int argc, char** argv){
if(argc != 2) return 1;
KEY_TYPE key;
sscanf(argv[1], "%d", &key);
VALUE_TYPE value = fib(key);
printf("fib(%d) = %lld\n", key, value);
return 0;
}
在C中的实际实现是正确的(通过使用clang进行了测试。)在Node.js中,它对于较小的整数非常有效,但是当我尝试47时,
fib(47)
返回-1323752223是不正确的。var Module = require("./fib.js");
var fib = Module.cwrap("fib", "number", ["number"]);
for(var i = 1; i <= 90; i++){
console.log(i, fib(i));
}
45 1134903170
46 1836311903
47 -1323752223 <-- overflow?
48 512559680 <-- all numbers are incorrect after this point
49 -811192543
这是为什么?我用来编译C代码的命令如下:
emcc fib.c -O1 -o fib.js -s EXPORTED_FUNCTIONS="['_fib']"
最佳答案
JS中的AFAIK中,所有数字都表示为double
,并且使用它们模拟了Asm.js子集中的整数。但是64位int不能用double
表示,因此我记得,在Emscripten调用约定中,使用某些全局临时变量返回了long long
的最高32位。
使用调试信息(-g3
编译器选项)编译程序(您可能必须尝试不同的优化级别:在-O0
上生成的代码可能太吵,但是在-O3
上可能不容易理解)和检查main
函数以了解如何调用_fib
以及如何获取返回值。但是我担心,此调用约定可能会在将来的Emscripten版本中更改。同时,您可以尝试阅读Emscripten的val.h
和bind.h
上的文档,但是我自己从未使用过它们。
关于javascript - Emscripten中的“大”整数,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/47323018/