【发布时间】:2011-03-19 23:32:28
【问题描述】:
我需要将很多公式从 C 移植到 Python,反之亦然。确保过程中没有中断的最佳方法是什么?
我主要担心自动 int/int = float 转换。
【问题讨论】:
标签: python-3.x
我需要将很多公式从 C 移植到 Python,反之亦然。确保过程中没有中断的最佳方法是什么?
我主要担心自动 int/int = float 转换。
【问题讨论】:
标签: python-3.x
您可以使用// 运算符。它执行整数除法,但与您对 C 的期望不同:
引用here:
// 运算符执行一种古怪的整数除法。当。。。的时候 结果是肯定的,你可以想到 它截断(不四舍五入)为 0 小数位,但要小心 那个。
当整数除负数时, // 运算符“向上”四舍五入 到最接近的整数。数学上 说起来,它是四舍五入的,因为 -6 小于 -5,但它可能会跳闸 如果你期待它,你就起来 截断为 -5。
例如,Python 中的-11 // 2 返回-6,而C 中的-11 / 2 返回-5。
我建议编写一个“模拟”C 行为的自定义整数除法函数并对其进行彻底的单元测试。
我在上面链接的页面也有一个指向PEP 238 的链接,其中包含一些关于除法的有趣背景信息以及从 Python 2 到 3 的变化。关于整数除法的使用方法有一些建议,例如 divmod(x, y)[0] 和int(x/y) 为正数,也许你会在那里找到更多有用的东西。
【讨论】:
//和C的地板事业部不一样。
// 的“古怪”定义才能使%不古怪。
在 C 中:
-11/2 = -5
在 Python 中:
-11/2 = -5.5
在 Python 中也是如此:
-11//2 = -6
要实现类似 C 的行为,请在 Python 中编写 int(-11/2)。这将评估为-5。
【讨论】:
反方向:
由于 Python 3 divmod(或 //)整数除法要求余数在非零余数情况下与除数具有相同的符号,因此它与许多其他语言不一致(引用自 1.4. Integer Arithmetic )。
为了让你的“C-like”结果与 Python 相同,你应该将余数结果与除数进行比较(建议:通过 xor 对符号位等于 1,或乘以负结果),如果不同,添加余数的除数,商减1。
// Python Divmod requires a remainder with the same sign as the divisor for
// a non-zero remainder
// Assuming isPyCompatible is a flag to distinguish C/Python mode
isPyCompatible *= (int)remainder;
if (isPyCompatible)
{
int32_t xorRes = remainder ^ divisor;
int32_t andRes = xorRes & ((int32_t)((uint32_t)1<<31));
if (andRes)
{
remainder += divisor;
quotient -= 1;
}
}
(感谢 Gawarkiewicz M. 指出这一点。)
【讨论】:
用 C 语义计算整数除法的一些方法如下:
def div_c0(a, b):
if (a >= 0) != (b >= 0) and a % b:
return a // b + 1
else:
return a // b
def div_c1(a, b):
q, r = a // b, a % b
if (a >= 0) != (b >= 0) and a % b:
return q + 1
else:
return q
def div_c2(a, b):
q, r = divmod(a, b)
if (a >= 0) != (b >= 0) and a % b:
return q + 1
else:
return q
def mod_c(a, b):
return (a % b if b >= 0 else a % -b) if a >= 0 else (-(-a % b) if b >= 0 else a % b)
def div_c3(a, b):
r = mod_c(a, b)
return (a - r) // b
有时间安排:
n = 100
l = [x for x in range(-n, n + 1)]
ll = [(a, b) for a, b in itertools.product(l, repeat=2) if b]
funcs = div_c0, div_c1, div_c2, div_c3
for func in funcs:
correct = all(func(a, b) == funcs[0](a, b) for a, b in ll)
print(func.__name__, 'correct:', correct)
%timeit [func(a, b) for a, b in ll]
print()
div_c0 correct: True
100 loops, best of 3: 8.42 ms per loop
div_c1 correct: True
100 loops, best of 3: 10 ms per loop
div_c2 correct: True
100 loops, best of 3: 12.3 ms per loop
div_c3 correct: True
100 loops, best of 3: 13.1 ms per loop
表示第一种方法最快。
要使用 Python 实现 C 的 %,请参阅 here。
【讨论】:
您需要知道公式的作用,并了解 C 实现以及如何在 Python 中实现它。但除非你在做整数数学,否则它应该非常相似,如果你正在在做整数数学,问题就是为什么。 :)
整数数学要么是出于某些特定目的(通常与计算机相关),要么是因为在进行大量计算时它比浮点数更快,就像 Fractint 对分形所做的那样,在这种情况下,Python 通常不是正确的选择。 ;)
【讨论】: