[英]Precision of calculations in Python 3
在Python中,我得到了简单计算的意外结果:
100 - 123.123
返回值:
-23.123000000000005
我预期输出为-23.123。
所以我尝试了:
import numpy as np
np.float64(100) - np.float64(123.123)
返回值:
-23.123000000000005
我预期输出为-23.123。
有什么建议如何获得更精确的结果?
您已经在python doc中定义了这种效果:
https://docs.python.org/2/tutorial/floatingpoint.html
您可以在打印结果中设置结果的格式,使其具有所需的3位数字:
print("%.3f" % np.float64(100) - np.float64(123.123))
任何建议如何获得更精确的结果?
当然,有几个选项可供重复使用。
问题不在于数字的外观,而在于其在技术上如何“内在”计算过程。 浮点数表示的IEEE标准规范在技术上相当“短”,因为在某些中等深度的迭代数(重新)处理中很快就可以看到, 因此python以及其他语言已经扩展了精度数表示+处理工具 (任意精度数学)-看:
decimal
模块: 我心爱的人 几年前,我确实进行了一些扩展的精度计算(由于非常丑陋的条件问题,超过了1000个小数位),使用纯十进制函数甚至使numpy
数组(作为存储类)+ scipy.optimize.fmin_l_bfgs()
求解器继续使用这些工具,并保持在这些扩展的精度之内……很酷)
import decimal
decX = np.asarray( ( decimal.Decimal( 3.4 ), decimal.Decimal( 3.5 ), decimal.Decimal( 3.7 ), decimal.Decimal( 4.3 ), ) )
decY = np.asarray( ( decimal.Decimal( 65 ), decimal.Decimal( 85 ), decimal.Decimal( 97 ), decimal.Decimal( 100 ), ) )
def pure_dec_LSQ_5DoF( decCTX, Xopt, decX_measured, decY_measured ): # [PERF] ~ 2400 [us] @ .prec = 14
return decCTX.add( decCTX.add( decCTX.power( decCTX.subtract( decCTX.fma( Xopt[0], decCTX.power( Xopt[4], decCTX.fma( Xopt[1], decX_measured[0], Xopt[2] ) ), Xopt[3] ), decY_measured[0] ), decimal.Decimal( 2 ) ), # ~ 2800 [us] @ .prec = 28
decCTX.power( decCTX.subtract( decCTX.fma( Xopt[0], decCTX.power( Xopt[4], decCTX.fma( Xopt[1], decX_measured[1], Xopt[2] ) ), Xopt[3] ), decY_measured[1] ), decimal.Decimal( 2 ) ) # ~ 7700 [us] @ .prec = 100
), # ~ 1340 [ms] @ .prec = 1000
decCTX.add( decCTX.power( decCTX.subtract( decCTX.fma( Xopt[0], decCTX.power( Xopt[4], decCTX.fma( Xopt[1], decX_measured[2], Xopt[2] ) ), Xopt[3] ), decY_measured[2] ), decimal.Decimal( 2 ) ), #
decCTX.power( decCTX.subtract( decCTX.fma( Xopt[0], decCTX.power( Xopt[4], decCTX.fma( Xopt[1], decX_measured[3], Xopt[2] ) ), Xopt[3] ), decY_measured[3] ), decimal.Decimal( 2 ) ) #
)
)
当然,有1000个小数位很多,但是要付出时间才能让数值过程执行到这些深度而又不损失精度。
>>> with decimal.localcontext() as locCTX:
... for aPREC in range( 20, 31 ):
... locCTX.prec = aPREC
... ( pure_dec_LSQ_5DoF( locCTX,
dec_fmin_x0_SEARCH_TRIM_TO_BE_PRECISE,
decX,
decY
),
pure_dec_RESi( locCTX,
dec_fmin_x0_SEARCH_TRIM_TO_BE_PRECISE,
decX,
decY
)
)
...
(Decimal('0.038471115298826195147'), (Decimal('0.023589050081780503'), Decimal('-0.082605913918299990'), Decimal('0.150647690402532134'), Decimal('-0.091630826566012630')))
(Decimal('0.0384711152988261953165'), (Decimal('0.0235890500817804889'), Decimal('-0.0826059139182999933'), Decimal('0.1506476904025321349'), Decimal('-0.0916308265660126301')))
(Decimal('0.03847111529882619531420'), (Decimal('0.02358905008178048823'), Decimal('-0.08260591391829999331'), Decimal('0.15064769040253213501'), Decimal('-0.09163082656601263007')))
(Decimal('0.038471115298826195324048'), (Decimal('0.023589050081780488368'), Decimal('-0.082605913918299993309'), Decimal('0.150647690402532135021'), Decimal('-0.091630826566012630071')))
(Decimal('0.0384711152988261953231489'), (Decimal('0.0235890500817804883582'), Decimal('-0.0826059139182999933087'), Decimal('0.1506476904025321350199'), Decimal('-0.0916308265660126300707')))
(Decimal('0.03847111529882619532322276'), (Decimal('0.02358905008178048835950'), Decimal('-0.08260591391829999330863'), Decimal('0.15064769040253213501998'), Decimal('-0.09163082656601263007070')))
(Decimal('0.038471115298826195323213788'), (Decimal('0.023589050081780488359358'), Decimal('-0.082605913918299993308625'), Decimal('0.150647690402532135019974'), Decimal('-0.091630826566012630070702')))
(Decimal('0.0384711152988261953232136753'), (Decimal('0.0235890500817804883593541'), Decimal('-0.0826059139182999933086251'), Decimal('0.1506476904025321350199740'), Decimal('-0.0916308265660126300707023')))
(Decimal('0.03847111529882619532321367314'), (Decimal('0.02358905008178048835935336'), Decimal('-0.08260591391829999330862505'), Decimal('0.15064769040253213501997413'), Decimal('-0.09163082656601263007070231')))
(Decimal('0.038471115298826195323213665675'), (Decimal('0.023589050081780488359353229'), Decimal('-0.082605913918299993308625043'), Decimal('0.150647690402532135019974132'), Decimal('-0.091630826566012630070702306')))
(Decimal('0.0384711152988261953232136649869'), (Decimal('0.0235890500817804883593532187'), Decimal('-0.0826059139182999933086250437'), Decimal('0.1506476904025321350199741307'), Decimal('-0.0916308265660126300707023064')))
能够将搜索过程减少到最低限度,如下所示:
dec_fmin_x0_SEARCH_ADAPTIVE = np.asarray( ( decimal.Decimal( -101000000010553.05594055493064099456356276561617988943684402001075635 ),
decimal.Decimal( -8.660605201193546246 ),
decimal.Decimal( 0.00021842459768549 ),
decimal.Decimal( 99.9259163119085989057939988625810620201012857893012816197730189907743792931209843327426339987914746365315172977942868845721827684076717423116961495794648319380554868846324870276029626886129186998300662535940937605435069739237317269895772 ),
decimal.Decimal( 2.64971757369295002249999999827154484100152060917026952223212241653783649669777780217778380697777777796977777777969777777777969777777779697777777796977777805877778058777780587777777800577777780057777778005777777800577777774817774778285740 ),
)
)
mpmath
模块: import mpmath
def fmp_5DoF( Xopt, matX_measured , matY_measured ):
return ( ( ( Xopt[0] * mpmath.power( Xopt[4], ( Xopt[1] * matX_measured[0] + Xopt[2] ) ) + Xopt[3] ) - matY_measured[0] )**2
+ ( ( Xopt[0] * mpmath.power( Xopt[4], ( Xopt[1] * matX_measured[1] + Xopt[2] ) ) + Xopt[3] ) - matY_measured[1] )**2
+ ( ( Xopt[0] * mpmath.power( Xopt[4], ( Xopt[1] * matX_measured[2] + Xopt[2] ) ) + Xopt[3] ) - matY_measured[2] )**2
+ ( ( Xopt[0] * mpmath.power( Xopt[4], ( Xopt[1] * matX_measured[3] + Xopt[2] ) ) + Xopt[3] ) - matY_measured[3] )**2
)
>>> fmp_5DoF( [ -1.01e+14, -8.44017374, -7.84602606e-4, 9.99261072e+1, 2.71792286 ], matX, matY )
mpf('0.038471245878352295')
>>> mpmath.mp.prec
53
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.