📄 ck_math.cpp
字号:
#include "wymath.h"#include "wy__math.h"#include "wystr.h"#include <iostream>#include <stdlib.h>#include <stdio.h>static const double ErrRate_Sci=1e-13; // error ratio limit of _scifstatic const double ErrRate_Float=1e-18;struct ChkSmpDouble { const char* nstr; size_t slen; double ans; void verify(void) { const int PrecisionDigits=14; const double MaxErrRat=std::pow(10.0,-PrecisionDigits); WyRet r; const char* cptr; double res; if((r=Wy::_strnum(res,&cptr,WyCSeg(nstr,slen)))!=Ok) { WY_THROW(r); } if(cptr-nstr!=(int)slen) { WY_THROW( WyRet() ); } if(ans!=0.0) { const double err_rat=std::fabs((res-ans)/ans); if(err_rat>MaxErrRat) { std::cerr.precision(PrecisionDigits+2); std::cerr << "ans=" << ans << ", res=" << res << ". error ratio=" << err_rat << std::endl; WY_THROW( WyRet() ); } } else { if(std::fabs(res)>MaxErrRat) { std::cerr.precision(PrecisionDigits+2); std::cerr << "ans=" << ans << ", res=" << res << std::endl; WY_THROW( WyRet() ); } } };};struct ChkSmpFloat { typedef float CkType; const char* nstr; size_t slen; double ans; void verify(void) { const int PrecisionDigits=7; const double MaxErrRat=std::pow(10.0,-PrecisionDigits); WyRet r; const char* cptr; CkType res; if((r=Wy::_strnum(res,&cptr,WyCSeg(nstr,slen)))!=Ok) { WY_THROW(r); } if(cptr-nstr!=(int)slen) { WY_THROW( WyRet() ); } if(ans!=0.0) { const double err_rat=std::fabs((res-ans)/ans); if(err_rat>MaxErrRat) { std::cerr.precision(PrecisionDigits+2); std::cerr << "ans=" << ans << ", res=" << res << ". error ratio=" << err_rat << std::endl; WY_THROW( WyRet() ); } } else { if(std::fabs(res)>MaxErrRat) { std::cerr.precision(PrecisionDigits+2); std::cerr << "ans=" << ans << ", res=" << res << std::endl; WY_THROW( WyRet() ); } } };};static void t_strnum(void){ ChkSmpDouble chk_dtab[]={ {".0",2,0.0}, {".00",3,0.0}, {"1",1,1.0}, {"0.045600",8,0.0456}, {"00.045600",9,0.0456},{".045600",7,0.0456}, {"1e2",3,100.0}, {"-23.456",7,-23.456}, {"23.456e-1",9,2.3456}, {".123456789e0",12,0.123456789}, {".123456789e-1",13,0.123456789e-1}, {".123456789e-2",13,0.123456789e-2}, {".123456789e-3",13,0.123456789e-3}, {".123456789e-4",13,0.123456789e-4}, {".123456789e-5",13,0.123456789e-5}, {".123456789e-300",15,0.123456789e-300}, {".123456789e-301",15,0.123456789e-301}, {".123456789012345678e0",21,0.123456789012345678}, {".12345678901234567e-1",21,0.12345678901234567e-1}, {".12345678901234567e-2",21,0.12345678901234567e-2}, {".12345678901234567e-3",21,0.12345678901234567e-3}, {".12345678901234567e-4",21,0.12345678901234567e-4}, {".12345678901234567e-5",21,0.12345678901234567e-5}, {".12345678901234567e+1",21,0.12345678901234567e+1}, {".12345678901234567e+2",21,0.12345678901234567e+2}, {".12345678901234567e+3",21,0.12345678901234567e+3}, {".12345678901234567e+4",21,0.12345678901234567e+4}, {".12345678901234567e+5",21,0.12345678901234567e+5}, {".12345678901234567e+300",23,0.12345678901234567e+300}, {".12345678901234567e+301",23,0.12345678901234567e+301}, }; for(size_t i=0; i<sizeof(chk_dtab)/sizeof(ChkSmpDouble); ++i) { chk_dtab[i].verify(); }; ChkSmpFloat chk_ftab[]={ {".0",2,0.0}, {".00",3,0.0}, {"1",1,1.0}, {"0.045600",8,0.0456}, {"00.045600",9,0.0456},{".045600",7,0.0456}, {"1e2",3,100.0}, {"-23.456",7,-23.456}, {"23.456e-1",9,2.3456}, {".123456789e0",12,0.123456789}, {".123456789e-1",13,0.123456789e-1}, {".123456789e-2",13,0.123456789e-2}, {".123456789e-3",13,0.123456789e-3}, {".123456789e-4",13,0.123456789e-4}, {".123456789e-5",13,0.123456789e-5}, {".123456789e-30",14,0.123456789e-30}, {".123456789e-31",14,0.123456789e-31}, {".123456789012345678e0",21,0.123456789012345678}, {".12345678901234567e-1",21,0.12345678901234567e-1}, {".12345678901234567e-2",21,0.12345678901234567e-2}, {".12345678901234567e-3",21,0.12345678901234567e-3}, {".12345678901234567e-4",21,0.12345678901234567e-4}, {".12345678901234567e-5",21,0.12345678901234567e-5}, {".12345678901234567e+1",21,0.12345678901234567e+1}, {".12345678901234567e+2",21,0.12345678901234567e+2}, {".12345678901234567e+3",21,0.12345678901234567e+3}, {".12345678901234567e+4",21,0.12345678901234567e+4}, {".12345678901234567e+5",21,0.12345678901234567e+5}, {".12345678901234567e+30",22,0.12345678901234567e+30}, {".12345678901234567e+31",22,0.12345678901234567e+31}, }; for(size_t i=0; i<sizeof(chk_ftab)/sizeof(ChkSmpFloat); ++i) { chk_ftab[i].verify(); }; WyRet r; // check error (double) { const char nstr[]="12.-34"; const char* cptr; double res; if((r=Wy::_strnum(res,&cptr,WyCSeg(nstr,sizeof(nstr)-1)))!=Wym_EBADMSG) { WY_THROW(r); } } // check error (float) { const char nstr[]="12.-34"; const char* cptr; float res; if((r=Wy::_strnum(res,&cptr,WyCSeg(nstr,sizeof(nstr)-1)))!=Wym_EBADMSG) { WY_THROW(r); } }};static void t_sci(void){ struct ChkSmp { double num; double frac; double p10; void verify(void) const { const double ErrRate=1e-14; double t1,t2; try { t1=WyMath::_scif(num,t2); if(frac==0) { if(std::fabs(t1)>ErrRate) { WY_THROW( WyRet() ); } } else { if(std::fabs((t1-frac)/frac)>ErrRate) { WY_THROW( WyRet() ); } } if(p10==0) { if(std::fabs(t2)>ErrRate) { WY_THROW( WyRet() ); } } else { if(std::fabs((t2-p10)/p10)>ErrRate) { WY_THROW( WyRet() ); } } } catch(...) { std::cerr << "ChkSmp={" << num << "," << frac << "," << p10 << "} t1=" << t1 << " ,t2=" << t2 << std::endl; throw; }; }; } const chk_tab[]={ // num, frac, p10 {0.0,0.0,0.0}, {0.1,1.0,-1.0}, {0.01,1.0,-2.0}, {1,1.0,0.0}, {10,1.0,1.0}, {100,1.0,2.0}, {0.5,5.0,-1.0}, {5,5.0,0.0}, {50,5.0,1.0}, }; for(size_t i=0; i<sizeof(chk_tab)/sizeof(ChkSmp); ++i) { chk_tab[i].verify(); } // // chk Math::_scif(...) conversion error limit // for(int i=0; i<65535L; ++i) { static int rnd_sign=0; double rnd0=::rand()/(RAND_MAX+1.0); // rand [0,1) double rnd1=200-(::rand()%400); // rand [-199,200] double rnda=rnd0*::pow(10.0,rnd1); ++rnd_sign; if(rnd_sign&1) { rnda=-rnda; } //std::cout << rnda << std::endl; double a1,a2; a1=WyMath::_scif(rnda,a2); if(a1>0) { // chk a1 range [1,10) if(a1<1.0) { WY_THROW( WyRet() ); } else if(a1>=10.0) { WY_THROW( WyRet() ); } else {} } else if(a1<0) { // chk a1 range (-10,-1] if(a1<=-10.0) { WY_THROW( WyRet() ); } else if(a1>-1.0) { WY_THROW( WyRet() ); } else {} } else { if(rnda!=0) { WY_THROW( WyRet() ); } } // chk not much error of the result { const double ans=a1*::pow(10.0,a2); // convert back to check error ratio if(rnda!=0) { double err_rate=std::abs((ans-rnda)/rnda); if(err_rate>ErrRate_Sci) { std::cerr << "err_rate=" << err_rate << std::endl; WY_THROW( WyRet() ); } } else { if(ans!=0) { WY_THROW( WyRet() ); } } } }};void ck_math(void){ t_strnum(); t_sci();};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -