我想访问内置函数round()
的源代码,以允许我创建一个非常相似的函数。我如何访问此源代码以及编辑/使用它的容易程度?
我感兴趣的原因是内置函数round()
即使数字为负数也会将整数转换为浮点数。
例如:
round(1234.5678,-2)
返回
1200.0
我想创建一个返回整数的函数。我确信还有其他方法可以实现相同的结果,但是我想看看内置函数如何实现这个任务,因为我希望它的效率相当高。
答案 0 :(得分:1)
来源似乎是:https://github.com/python/cpython/blob/master/Python/pymath.c
double
round(double x)
{
double absx, y;
absx = fabs(x);
y = floor(absx);
if (absx - y >= 0.5)
y += 1.0;
return copysign(y, x);
}
其中copysign是:
double
copysign(double x, double y)
{
/* use atan2 to distinguish -0. from 0. */
if (y > 0. || (y == 0. && atan2(y, -1.) > 0.)) {
return fabs(x);
} else {
return -fabs(x);
}
}
答案 1 :(得分:1)
只需扩展Mark Dickinson的注释,并确保我自己理解,CPython round
function就分布在代码库的几个部分。
round(number, ndigits)
首先在对象上查找并调用__round__
方法。这是由C函数builtin_round_impl
in bltinmodule.c
对于float
,这会调用float.__round__
方法,该方法在float___round___impl
in floatobject.c:1045中实现,但是floatobject.c.h中有一个存根入口点,我认为它主要由{{ 3}}工具。此标头也是其PyMethodDef
被定义为FLOAT___ROUND___METHODDEF
C函数float___round___impl
首先检查是否未指定ndigits
(即没有传递或以None
传递),在这种情况下,它将从{ C标准库(或pymath.c的版本作为后备)。
如果指定了ndigits
,则它可能会调用Python's argument clinic的版本。此代码以53位精度工作,因此可以调整浮点舍入模式,并且通常是很漂亮的代码,但是基本上它将双精度数转换为具有给定精度的字符串,然后再转换回双精度数
round
double_round
in floatobject.c:927的另一个版本执行的功能基本上是round(x * 10**ndigits) / 10**ndigits
,但是这些额外的操作会降低结果的精度
请注意,如small number of platforms所述,较高精度的版本将对double_round
at floatobject.c:985中的版本和NumPy中的等效版本给出不同的答案。例如,round(0.075, 2)
的内置回合结果为0.07,而numpy和R给出0.08。我发现最简单的方法是使用R模块来查看浮点数的十进制扩展:
from decimal import Decimal
print(Decimal(0.075))
给定:0.0749999999999999972…
,即0.075不能由(二进制)浮点数精确表示,并且最接近的数字恰好稍小,因此将其舍入为0.07。而here给出0.08的原因是它有效地round(0.075 * 100) / 100
并且中间值恰好取整,即:
print(Decimal(0.075 * 100))
精确给出7.5
,将其精确舍入到8
。