我一直在不同的语言和实现中实施相同的代码(在二十一点游戏中发牌而不爆牌的方式数量)。我注意到一个奇怪的事情是,Python调用C中的partitions函数的实现实际上比整个用C编写的程序略快。对于其他语言也是如此(Ada vs Python calling Ada, Nim vs Python calling Nim)。这似乎与我的直觉相反 - 你有什么想法吗?
所有代码都在我的GitHub存储库中:
所有代码都在我的GitHub存储库中:
https://github.com/octonion/puzzles/tree/master/blackjack
这是C代码,使用'gcc -O3 outcomes.c'编译。#include <stdio.h>
int partitions(int cards[10], int subtotal)
{
//writeln(cards,subtotal);
int m = 0;
int total;
// Hit
for (int i = 0; i < 10; i++)
{
if (cards[i] > 0)
{
total = subtotal + i + 1;
if (total < 21)
{
// Stand
m += 1;
// Hit again
cards[i] -= 1;
m += partitions(cards, total);
cards[i] += 1;
}
else if (total == 21)
{
// Stand; hit again is an automatic bust
m += 1;
}
}
}
return m;
}
int main(void)
{
int deck[] =
{ 4, 4, 4, 4, 4, 4, 4, 4, 4, 16 };
int d = 0;
for (int i = 0; i < 10; i++)
{
// Dealer showing
deck[i] -= 1;
int p = 0;
for (int j = 0; j < 10; j++)
{
deck[j] -= 1;
int n = partitions(deck, j + 1);
deck[j] += 1;
p += n;
}
printf("Dealer showing %i partitions = %i\n", i, p);
d += p;
deck[i] += 1;
}
printf("Total partitions = %i\n", d);
return 0;
}
这是一个C函数,使用'gcc -O3 -fPIC -shared -o libpartitions.so partitions.c'编译。
int partitions(int cards[10], int subtotal)
{
int m = 0;
int total;
// Hit
for (int i = 0; i < 10; i++)
{
if (cards[i] > 0)
{
total = subtotal + i + 1;
if (total < 21)
{
cards[i] -= 1;
// Stand
m += 1;
// Hit again
m += partitions(cards, total);
cards[i] += 1;
}
else if (total == 21)
{
// Stand; hit again is an automatic bust
m += 1;
}
}
}
return m;
}
这里是C函数的Python包装器:
#!/usr/bin/env python
from ctypes import *
import os
test_lib = cdll.LoadLibrary(os.path.abspath("libpartitions.so"))
test_lib.partitions.argtypes = [POINTER(c_int), c_int]
test_lib.partitions.restype = c_int
deck = ([4]*9)
deck.append(16)
d = 0
for i in xrange(10):
# Dealer showing
deck[i] -= 1
p = 0
for j in xrange(10):
deck[j] -= 1
nums_arr = (c_int*len(deck))(*deck)
n = test_lib.partitions(nums_arr, c_int(j+1))
deck[j] += 1
p += n
print('Dealer showing ', i,' partitions =',p)
d += p
deck[i] += 1
print('Total partitions =',d)
dlopen
和dlsym
调用函数指针,而不是正常调用。我无法想象为什么这样会更快,但我也无法想象为什么Python会更快,这至少可以缩小我们的想象空间。 :) - abarnertdlopen
和dlsym
调用 C 语言编写的程序比独立的 C 语言程序运行速度更快。这是我的代码。 - Christopher D. Long