RealLib ã§ã¯ããã誤差ã¼ãå®æ°è¨ç®
RealLib ã®ã½ã¼ã¹ã³ã¼ãèªã¿ãå§ããã¯ãã ã£ããã§ããããªãã ãå
¨ç¶é²ãã§ãªãã®ã§é©å½ãªã¾ã¨ãã¨ã³ããªã§ãè¶ãæ¿ãã¾ãï¼ RealLib ãæ®éã«ãã£ãããããã®ã§ç´¹ä»ãã¾ãããããªãã¾ããã®ã§ç´¹ä»è¨äºã§ãã
å®æ°è¨ç®ã¨èª¤å·®
ããã¦ãã®ããã°ã©ãã³ã°è¨èªã®ãå®æ° = æµ®åå°æ°ç¹æ°ãã®è¨ç®ã«ã¯ã誤差ããããã¾ãããã¨ãã°Pythonã®ã°ããï¼
Python 2.5 (r25:51908, Sep 19 2006, 09:52:17) [MSC v.1310 32 bit (Intel)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> 0.1 + 0.1 + 0.1 - 0.3 5.5511151231257827e-017
0.1 ã 3 å足ãã¦ã 0.3 ã«ã¯ãªãã¾ãããå°ãã ãããã¡ãã£ã¦ã¾ãã
ãã®ä¾ã®ã°ããã誤差ã®åå ã¯ããæµ®åå°æ°ç¹æ°ãã2é²æ°ã§è¡¨ç¾ããã¦ãããã¨ã§ãã"0.1" ã¯2é²æ°ã§æ¸ãã¨ç¡éå°æ°ãªã®ã§ãéä¸ã§æã¡åã£ã¦è¨æ¶ããã¦ãã¾ããæ£ç¢ºãª "0.1" ã¨ã¯å°ããããå¤ã«ãªã£ã¦ãã¾ãã®ã§ãã
ããã§ã¯å°ãå ´åã®ããã«ãå¤ãã®ããã°ã©ãã³ã°è¨èªã«ã¯ã10é²æ°ã§å®æ°ãè¨æ¶ãããBigDecimalãã®ãããªã©ã¤ãã©ãªãç¨æããã¦ãã¾ããã¾ãã¾ã Python ã®ã°ããï¼
>>> Decimal("0.1") + Decimal("0.1") + Decimal("0.1") - Decimal("0.3") Decimal("0.0")
ããã¿ãª "0.0" ã«ãªãã¾ããï¼
ã§ã¯ãDecimal ã®ãããªã©ã¤ãã©ãªã使ãã°ãå®æ°è¨ç®ã®èª¤å·®ã¯å®å ¨ã«æ¶ãã¦ãªããªãã®ã§ããããï¼ çãã¯å¦ã
>>> Decimal(8) / Decimal(7) * Decimal(7) Decimal("8.000000000000000000000000001")
"8/7" ã¯10é²æ°ã§ã¯ç¡éå°æ°ã«ãªã£ã¦ãã¾ãã®ã§ãDecimalã§ãéä¸ã§æã¡åããã¦ãã¾ãã¾ãããã®çµæã7åãã¦ãå ã®8ã«ã¯æ»ããããã£ã±ãå¾®å¦ã«ããã¾ããPythonã®ããã©ã«ãã§ã¯éä¸ã®æã¡åãã¯28ã±ã¿ã§ãããããã調æ´ãã¦ã©ãã ãé·ãã«ã¨ã£ã¦ãã
>>> getcontext().prec = 80 >>> Decimal(8) / Decimal(7) * Decimal(7) Decimal("7.999999999999999999999999999999999999999999999999999999999999999999999 9999999997") >>> getcontext().prec = 300 >>> Decimal(8) / Decimal(7) * Decimal(7) Decimal("8.000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 0000000000000000000000000000000000000000000000000000000000000000000002")
ããããã®ã¯ããã¾ããã7é²æ°ã§è¡¨ç¾ããã©ã¤ãã©ãªãå°å ¥ããã°ã»ã»ã»ï¼ï¼ãã¨æããèãã¦ãã¾ãã¾ãããä½é²æ°ã§è¡¨ç¾ãããã¨ããæçæ°ã§è¿ä¼¼ãã¦ããéãã¯ããã¨ãã° sqrt ã sin ã®ãããªç¡çæ°ãè¿ãè¨ç®ãå ¥ããã¨ããã«ãã¡ãã£ã¨ããã¦ãã¾ããã¨ã¯é¿ãããã¾ãããï¼å·§ãå®è£ ããªãéãï¼è¨ç®ãç¹°ãè¿ããã³ã«ãã®èª¤å·®ã¯å°ããã¤ç©ãã£ã¦ããã¾ãã
â» CPUã®æ©è½ã使ãæµ®åå°æ°ç¹æ¼ç®ã¨éã£ã¦ãBigDecimal ç³»ã®ã©ã¤ãã©ãªã§ã¯ãæã¡åãæ¡æ°ãå¿ è¦ãªã ããããã§ãé·ãè¨å®ãããã¨ãã§ãã¾ãããªã®ã§ããã¡ããã誤差ãç©ããç©ãã£ã¦ãåé¡ãªããããé·ãã«æ¡æ°ãåã£ã¦ããã°ããã®èª¤å·®ã¯å®ç¨ä¸ã¯åé¡ã«ãªããªãã§æ¸ã¿ã¾ãããã©ãã©ã®ãããã®èª¤å·®ãçºçããããããã¡ãã¡èããã®ã£ã¦å¤§å¤ã§ãã»ã»ã»ããï¼ãããã¯å¤§å¤ã§ãããããªãã¨æ°ã«ããããªãï¼
Exact Real Arithmetic
ã»ã»ã»ã¨ãããã¨ã§ãã誤差ã¼ãå®æ°è¨ç®ãã®ç»å ´ã§ãããç´¹ä»ãã RealLib 㯠C++ ã®ã©ã¤ãã©ãªã§ãReal ã¨ããã¯ã©ã¹ãæä¾ãã¦ãã¾ããååæ¼ç®çã ã¯å®ç¾©ããã¦ããã®ã§ãæ®éã®æ°å¤åã¨æã£ã¦ä½¿ããã¨ãã§ãã¾ããã³ã¼ãä¾ï¼
#include <iostream> #include <iomanip> using namespace std; #include <Real.h> using namespace RealLib; int main() { InitializeRealLib(); { cout << setiosflags(ios::fixed); Real r = Real("8") / Real("7") * Real("7"); cout << setprecision(28) << r << endl; // 28æ¡ç®ã¾ã§è¡¨ç¤º cout << setprecision(200) << r << endl; // 200æ¡ç®ã¾ã§è¡¨ç¤º cout << setprecision(3000) << r << endl; // 3000æ¡ç®ã¾ã§è¡¨ç¤º } FinalizeRealLib(); }
å®è¡çµæï¼
> rltest 8.0000000000000000000000000000 8.000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000 8.000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 ...(ä¸ç¥)... 00000000000000000000000000000000000000000000000000000000000000000000000000000000 000000000000000000000000000000000000000000
ãã¨ãä½åæ¡ã¾ã§è¡¨ç¤ºãããã¨ããr ã¯ããã¿ãª 8 ã§ããããã¾ããããããªãã®ã¯æçæ°æ¼ç®ã«éãã¾ããã
#include <iostream> #include <iomanip> using namespace std; #include <Real.h> using namespace RealLib; int main() { InitializeRealLib(); { cout << setiosflags(ios::fixed); Real s = cos( Pi/3 - Pi/2 ) * 2; // cos(-Ï/6)*2 = â3 Real ss = s * sqrt(Real("3")); // â3*â3 = 3 cout << setprecision(700) << s << endl << ss << endl; // 700æ¡è¡¨ç¤º } FinalizeRealLib(); }
åå¨çãã³ãµã¤ã³ãå¹³æ¹æ ¹ã®æ··ãã£ãè¨ç®ã§ãã»ã»ã»
> rltest2 1.732050807568877293527446341505872366942805253810380628055806979451933016908800 03708114618675724857567562614141540670302996994509499895247881165551209437364852 80932319023055820679748201010846749232650153123432669033228866506722546689218379 71227047131660367861588019049986537379859389467650347506576050756618348129606100 94760218719032508314582952395983299778982450828871446383291734722416398458785539 76679580638183536661108431737808943783161020883055249016700235207111442886959909 56365797087168498072899493296484283020786408603988738697537582317317831395992983 00783870287705391336956331210370726401924910676823119928837564114142201674275210 23729942708310598984594759876642888977961478379583902288548529 3.000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000000000000000000000 00000000000000000000000000000000000000000000000000000000000000
ããã¿ãª 3 ã«ãªãã¾ããâ3 ã®æ¹ã¯è¡¨ç¤ºã700æ¡ã§åã£ãé½åã§ããã¿ãª â3 ã§ã¯ããã¾ãããï¼ã¨ããããããã¿ãªã®â3ãæéå°æ°ã§è¡¨ç¤ºããã®ã¯ç¡çï¼ã表示ã®éãå¢ããã°ãããã§ãæ£ç¢ºã«â3ã«è¿ãå¤ã表示ããã¾ããPiãcosã使ã£ã¦é åãã«è¨ç®ããããã¨ãã£ã¦èª¤å·®ãä¹ããã¨ããªãã§ãã
使ãæ¹
é©å½ã« VC++ ã gcc ã§ãã«ããã¦é©å½ã«ä½¿ãã¨ä½¿ããã¨æãã¾ãï¼é©å½ã§ããã¾ããï¼ãå ¬éããã¦ãã½ã¼ã¹ã® Real.h ã¯ä¸ã«æãã°ã£ã¦ã¦ã確ãã©ãã operator/= ã®å®è£ ãæãç®ã«ãªã£ã¦ã¾ããã®ã§ç´ãã¦ãã使ã£ãæ¹ãè¯ãã¨æãã¾ãï¼é©å½ï¼ã
ããããé¢æ°ã¯ã²ã¨ã¨ããæä¾ããã¦ãã¾ããä¸è¦§è¡¨ï¼
- ã³ã³ã¹ãã©ã¯ã¿
- æååããæ§ç¯ Real("12.3456")
- doubleããæ§ç¯ Real(0.1) // ããã ã¨å½ç¶ãæ£ç¢ºãªã0.1ã«ã¯ãªããªãã®ã§æ³¨æ
- ååæ¼ç®
- å ç® Real + Real
- æ¸ç® Real - Real
- ä¹ç® Real * Real, Real * int, int * Real, Real * double, double * Real
- é¤ç® Real / Real, Real / int, int / Real, Real / double, double / Real
- å ç®ä»£å ¥ Real += Real
- æ¸ç®ä»£å ¥ Real -= Real
- ä¹ç®ä»£å ¥ Real *= Real, Real *= int, Real *= double
- é¤ç®ä»£å ¥ Real /= Real, Real /= int, Real /= double
- éæ° recip(Real)
- 符å·å転 - Real
- å®æ°
- Pi
- Ln2
- æ°å¦é¢æ°
ã¹ãã¼ã
精度ã«éãããªãã¨ãããã¨ã¯ããããè¨ç®ã大å¤ã§éãã ããã»ã»ã»ã¨ãæãã¾ãããæå¤ã¨ãåå使ããã¹ãã¼ããåºã¾ããä¾ï¼
#include <iostream> #include <iomanip> #include <boost/progress.hpp> using namespace std; #include <Real.h> using namespace RealLib; int main() { InitializeRealLib(); { cout << setiosflags(ios::fixed); cout << setprecision(1000); { boost::progress_timer t(cerr); Real e(0.0); Real q(1.0); for(int i=0; i<100000; ++i, q/=i) e += q; cout << e << endl; } { boost::progress_timer t(cerr); double e(0.0); double q(1.0); for(int i=0; i<100000; ++i, q/=i) e += q; cout << e << endl; } } FinalizeRealLib(); }
10ä¸åã«ã¼ãã精度1000æ¡ã¾ã§è¡¨ç¤ºãé度é¢ã§ã¯CPUã®æµ®åå°æ°ç¹æ¼ç®ã«ã¯æµãã¹ãããªãã§ãããæå ã®ãã·ã³ï¼PenM 1.7GHz, VC8 /Oxï¼ã§1ç§ãããã§è¨ç®å®äºãã¾ããã
2.718281828459045235360287471352662497757247093699959574966967627724076630353547 ...(ä¸ç¥)... 041718986106873969655212671546889570350354 1.11 s 2.718281828459045500000000000000000000000000000000000000000000000000000000000000 ...(ä¸ç¥)... 000000000000000000000000000000000000000000 0.01 s
å®éã¯500åãåãã°1000æ¡ã®ç²¾åº¦ã«ã¯éãã¦ããã®ã§ãããã§æã¡åãã¨0.05ç§ãããã§ããè²ã ãªæ¡ä»¶ãé©ãã使ãæ¹ãªã©ãªã©éãã¾ãã®ã§ãã¾ãæå³ã®ããæ¯è¼ã«ãªã£ã¦ãªãã®ã§ãããä¸å¿ãPythonã®Decimalã§ç²¾åº¦1000æ¡ã®500åã«ã¼ããåãã¨20ç§å¼±ãããã¾ãã
>>> from time import * >>> getcontext().prec = 1000 >>> def calc_e(): ... t = clock() ... e = Decimal(0) ... q = Decimal(1) ... for i in range(1,500): ... e += q ... q /= i ... print e ... print clock() - t, "sec" ... >>> calc_e() 2.718281828459045235360287471352662497757247093699959574966967627724076630353547 ...(ä¸ç¥)... 04171898610687396965521267154688957035044 19.4357855538 sec
æ¯è¼æ¼ç®è½ã¨ãç©´
ä¸åã ã注æããªãã¨åé¡ãªã¨ãããããã¾ããæ¯è¼æ¼ç®åã¯ä»¥ä¸ã®ãã®ãæä¾ããã¦ãã¾ãã»ã»ã»
- Real != Real
- Real < Real
- Real > Real
ã»ã»ã»ããããã§å®å ¨ã«çããå¤ã©ãããæ¯è¼ããã¨ãç¡éã«ã¼ãã«ãªã£ã¦å¸°ã£ã¦ãã¾ãããç¡é精度ã®ä¸ã§å¤ãéãæ¡ãè¦ã¤ãããçµæãè¿ãã¨ããå¦çãè¡ãããã®ã§ãçããå¤ã ã¨ã²ãããæ·±ãæ¡ã®å¤ã調ã¹ã«è¡ã£ãã£ããæ»ã£ã¦ããªããªã£ã¡ããã¾ããç¾ç¶ã§ã¯ããéããã¨ç¢ºå®ã«åãã£ã¦ããå¤ã©ããã®å¤§å°æ¯è¼ã§ãªãã¨ä½¿ãã®ã¯å±éºããã
妥åãã¦ã精度ãæå®ãã¦ããã®æ¡ã¾ã§åãã ã£ããåãã¨è¦ãªã大å°å¤å®ãã®ãããªãã®ãç¨æããã¦ãã¨ä¾¿å©ããã¨æã£ããã§ãããã©ããªã®ããªã