十年網(wǎng)站開發(fā)經(jīng)驗(yàn) + 多家企業(yè)客戶 + 靠譜的建站團(tuán)隊(duì)
量身定制 + 運(yùn)營(yíng)維護(hù)+專業(yè)推廣+無憂售后,網(wǎng)站問題一站解決
Python math 庫提供許多對(duì)浮點(diǎn)數(shù)的數(shù)學(xué)運(yùn)算函數(shù),math模塊不支持復(fù)數(shù)運(yùn)算,若需計(jì)算復(fù)數(shù),可使用cmath模塊(本文不贅述)。
創(chuàng)新互聯(lián)是一家專業(yè)提供曹妃甸企業(yè)網(wǎng)站建設(shè),專注與網(wǎng)站建設(shè)、網(wǎng)站設(shè)計(jì)、H5頁面制作、小程序制作等業(yè)務(wù)。10年已為曹妃甸眾多企業(yè)、政府機(jī)構(gòu)等服務(wù)。創(chuàng)新互聯(lián)專業(yè)網(wǎng)站建設(shè)公司優(yōu)惠進(jìn)行中。
使用dir函數(shù),查看math庫中包含的所有內(nèi)容:
1) math.pi????# 圓周率π
2) math.e????#自然對(duì)數(shù)底數(shù)
3) math.inf? ? #正無窮大∞,-math.inf? ? #負(fù)無窮大-∞
4) math.nan? ? #非浮點(diǎn)數(shù)標(biāo)記,NaN(not a number)
1) math.fabs(x)? ? #表示X值的絕對(duì)值
2) math.fmod(x,y)? ? #表示x/y的余數(shù),結(jié)果為浮點(diǎn)數(shù)
3) math.fsum([x,y,z])? ? #對(duì)括號(hào)內(nèi)每個(gè)元素求和,其值為浮點(diǎn)數(shù)
4) math.ceil(x)? ? #向上取整,返回不小于x的最小整數(shù)
5)math.floor(x)? ? #向下取整,返回不大于x的最大整數(shù)
6) math.factorial(x)? ? #表示X的階乘,其中X值必須為整型,否則報(bào)錯(cuò)
7) math.gcd(a,b)? ? #表示a,b的最大公約數(shù)
8)? math.frexp(x)? ? ? #x = i *2^j,返回(i,j)
9) math.ldexp(x,i)? ? #返回x*2^i的運(yùn)算值,為math.frexp(x)函數(shù)的反運(yùn)算
10) math.modf(x)? ? #表示x的小數(shù)和整數(shù)部分
11) math.trunc(x)? ? #表示x值的整數(shù)部分
12) math.copysign(x,y)? ? #表示用數(shù)值y的正負(fù)號(hào),替換x值的正負(fù)號(hào)
13) math.isclose(a,b,rel_tol =x,abs_tol = y)? ? #表示a,b的相似性,真值返回True,否則False;rel_tol是相對(duì)公差:表示a,b之間允許的最大差值,abs_tol是最小絕對(duì)公差,對(duì)比較接近于0有用,abs_tol必須至少為0。
14) math.isfinite(x)? ? #表示當(dāng)x不為無窮大時(shí),返回True,否則返回False
15) math.isinf(x)? ? #當(dāng)x為±∞時(shí),返回True,否則返回False
16) math.isnan(x)? ? #當(dāng)x是NaN,返回True,否則返回False
1) math.pow(x,y)? ? #表示x的y次冪
2) math.exp(x)? ? #表示e的x次冪
3) math.expm1(x)? ? #表示e的x次冪減1
4) math.sqrt(x)? ? #表示x的平方根
5) math.log(x,base)? ? #表示x的對(duì)數(shù)值,僅輸入x值時(shí),表示ln(x)函數(shù)
6) math.log1p(x)? ? #表示1+x的自然對(duì)數(shù)值
7) math.log2(x)? ? #表示以2為底的x對(duì)數(shù)值
8) math.log10(x)? ? #表示以10為底的x的對(duì)數(shù)值
1) math.degrees(x)? ? #表示弧度值轉(zhuǎn)角度值
2) math.radians(x)? ? #表示角度值轉(zhuǎn)弧度值
3) math.hypot(x,y)? ? #表示(x,y)坐標(biāo)到原點(diǎn)(0,0)的距離
4) math.sin(x)? ? #表示x的正弦函數(shù)值
5) math.cos(x)? ? #表示x的余弦函數(shù)值
6) math.tan(x)? ? #表示x的正切函數(shù)值
7)math.asin(x)? ? #表示x的反正弦函數(shù)值
8)?math.acos(x)? ? #表示x的反余弦函數(shù)值
9)?math.atan(x)? ? #表示x的反正切函數(shù)值
10) math.atan2(y,x)? ? #表示y/x的反正切函數(shù)值
11) math.sinh(x)? ? #表示x的雙曲正弦函數(shù)值
12) math.cosh(x)? ? #表示x的雙曲余弦函數(shù)值
13) math.tanh(x)? ? #表示x的雙曲正切函數(shù)值
14) math.asinh(x)? ? #表示x的反雙曲正弦函數(shù)值
15) math.acosh(x)? ? #表示x的反雙曲余弦函數(shù)值
16) math.atanh(x)? ? #表示x的反雙曲正切函數(shù)值
1)math.erf(x)? ? #高斯誤差函數(shù)
2) math.erfc(x)? ? #余補(bǔ)高斯誤差函數(shù)
3) math.gamma(x)? ? #伽馬函數(shù)(歐拉第二積分函數(shù))
4) math.lgamma(x)? ? #伽馬函數(shù)的自然對(duì)數(shù)
先來看一下 math 模塊中包含內(nèi)容,如下所示:
接下來具體看一下該模塊的常用函數(shù)和常量。
ceil(x)
返回 x 的上限,即大于或者等于 x 的最小整數(shù)??聪率纠?/p>
floor(x)
返回 x 的向下取整,小于或等于 x 的最大整數(shù)??聪率纠?/p>
fabs(x)
返回 x 的絕對(duì)值??聪率纠?/p>
fmod(x, y)
返回 x/y 的余數(shù),值為浮點(diǎn)數(shù)??聪率纠?/p>
factorial(x)
返回 x 的階乘,如果 x 不是整數(shù)或?yàn)樨?fù)數(shù)時(shí)則將引發(fā) ValueError??聪率纠?/p>
pow(x, y)
返回 x 的 y 次冪。看下示例:
fsum(iterable)
返回迭代器中所有元素的和。看下示例:
gcd(x, y)
返回整數(shù) x 和 y 的最大公約數(shù)。看下示例:
sqrt(x)
返回 x 的平方根??聪率纠?/p>
trunc(x)
返回 x 的整數(shù)部分。看下示例:
exp(x)
返回 e 的 x 次冪。看下示例:
log(x[, base])
返回 x 的對(duì)數(shù),底數(shù)默認(rèn)為 e??聪率纠?/p>
常量
tan(x)
返回 x 弧度的正切值??聪率纠?/p>
atan(x)
返回 x 的反正切值。看下示例:
sin(x)
返回 x 弧度的正弦值。看下示例:
asin(x)
返回 x 的反正弦值。看下示例:
cos(x)
返回 x 弧度的余弦值??聪率纠?/p>
acos(x)
返回 x 的反余弦值??聪率纠?/p>
decimal 模塊為正確舍入十進(jìn)制浮點(diǎn)運(yùn)算提供了支持,相比內(nèi)置的浮點(diǎn)類型 float,它能更加精確的控制精度,能夠?yàn)榫纫筝^高的金融等領(lǐng)域提供支持。
decimal 在一個(gè)獨(dú)立的 context 下工作,可以使用 getcontext() 查看當(dāng)前上下文,如下所示:
從上面的結(jié)果中我們可以看到 prec=28,這就是默認(rèn)的精度,我們可以使用 getcontext().prec = xxx 來重新設(shè)置精度。接下來通過具體示例看一下。
基本運(yùn)算
執(zhí)行結(jié)果:
上面結(jié)果是用了默認(rèn)精度,我們重新設(shè)置下精度再來看一下:
執(zhí)行結(jié)果:
random 模塊可以生成隨機(jī)數(shù),我們來看一下其常用函數(shù)。
random()
返回 [0.0, 1.0) 范圍內(nèi)的一個(gè)隨機(jī)浮點(diǎn)數(shù)。看下示例:
uniform(a, b)
返回 [a, b) 范圍內(nèi)的一個(gè)隨機(jī)浮點(diǎn)數(shù)??聪率纠?/p>
randint(a, b)
返回 [a, b] 范圍內(nèi)的一個(gè)隨機(jī)整數(shù)??聪率纠?/p>
randrange(start, stop[, step])
返回 [start, stop) 范圍內(nèi)步長(zhǎng)為 step 的一個(gè)隨機(jī)整數(shù)??聪率纠?/p>
choice(seq)
從非空序列 seq 返回一個(gè)隨機(jī)元素。 看下示例:
shuffle(x[, random])
將序列 x 隨機(jī)打亂位置??聪率纠?/p>
sample(population, k)
返回從總體序列或集合中選擇的唯一元素的 k 長(zhǎng)度列表,用于無重復(fù)的隨機(jī)抽樣??聪率纠?/p>
參考:
先說結(jié)論:這個(gè)問題是由于cpython的地板除運(yùn)算符(//)的實(shí)現(xiàn)不是 浮點(diǎn)除法+floor 來實(shí)現(xiàn)而是用了(被除數(shù) - 余數(shù))/除數(shù) 導(dǎo)致的。
PS:Jython下可以得到20.0,而PEP里規(guī)定了a // b應(yīng)該等于round(a/b),所以似乎這是cpython實(shí)現(xiàn)的一個(gè)bug?
首先先分析下1 / 0.05究竟應(yīng)該等于多少。答案就是精確的20.0。
簡(jiǎn)單解釋下:IEEE754浮點(diǎn)數(shù)規(guī)定,如果一個(gè)浮點(diǎn)數(shù)的值不能被精確記錄,那么它的值會(huì)被記成與這個(gè)數(shù)距離最近的可以被IEEE浮點(diǎn)數(shù)表示的數(shù)。
首先,0.05在二進(jìn)制下是無限循環(huán)小數(shù),自然不能被精確記錄,因此0.05這個(gè)浮點(diǎn)數(shù)的實(shí)際值是不等于0.05的,實(shí)際值是約為0.05 + 2.7e-18。
之后做浮點(diǎn)除法,實(shí)際上做的是1 / (0.05+2.7...e-18),這個(gè)除法的結(jié)果大約是20 - 1.1e-15。這個(gè)值也不能被精確表示,恰好離這個(gè)數(shù)最近的可以表示的值就是20.0,因此即使有浮點(diǎn)數(shù)誤差結(jié)果也是精確的20.0。
既然1/0.05就是20.0,那么對(duì)他做floor運(yùn)算自然也是20了。
現(xiàn)在的問題就是為什么1 // 0.05會(huì)變成19.0,要解決這個(gè)問題只能翻源碼看//運(yùn)算符的實(shí)現(xiàn)。
直接把cpython/floatobject.c at 829b49cbd2e4b1d573470da79ca844b730120f3d · python/cpython · GitHub 中實(shí)現(xiàn)//運(yùn)算的一段貼上來:
static PyObject *
float_divmod(PyObject *v, PyObject *w)
{
double vx, wx;
double div, mod, floordiv;
CONVERT_TO_DOUBLE(v, vx);
CONVERT_TO_DOUBLE(w, wx);
if (wx == 0.0) {
PyErr_SetString(PyExc_ZeroDivisionError, "float divmod()");
return NULL;
}
PyFPE_START_PROTECT("divmod", return 0)
mod = fmod(vx, wx);
/* fmod is typically exact, so vx-mod is *mathematically* an
exact multiple of wx. But this is fp arithmetic, and fp
vx - mod is an approximation; the result is that div may
not be an exact integral value after the division, although
it will always be very close to one.
*/
div = (vx - mod) / wx;
if (mod) {
/* ensure the remainder has the same sign as the denominator */
if ((wx 0) != (mod 0)) {
mod += wx;
div -= 1.0;
}
}
else {
/* the remainder is zero, and in the presence of signed zeroes
fmod returns different results across platforms; ensure
it has the same sign as the denominator. */
mod = copysign(0.0, wx);
}
/* snap quotient to nearest integral value */
if (div) {
floordiv = floor(div);
if (div - floordiv 0.5)
floordiv += 1.0;
}
else {
/* div is zero - get the same sign as the true quotient */
floordiv = copysign(0.0, vx / wx); /* zero w/ sign of vx/wx */
}
PyFPE_END_PROTECT(floordiv)
return Py_BuildValue("(dd)", floordiv, mod);
}
可以發(fā)現(xiàn)cpython中x // y的實(shí)現(xiàn)實(shí)際上是
round((x - fmod(x, y)) / y)
,其中fmod函數(shù)是求兩個(gè)浮點(diǎn)數(shù)相除的余數(shù)。
這樣一來就解釋的通了:在十進(jìn)制下,顯然1除以0.05的余數(shù)應(yīng)該是0.0。然而在IEEE浮點(diǎn)數(shù)環(huán)境中,0.05的實(shí)際值是約0.05 + 2.7e-18,略大于0.05,這樣一來1除以這個(gè)數(shù)的余數(shù)就成了約0.05 - 5e-17,從1中減掉這么多之后就只剩0.95了,除以0.05再round后變成19.0。