pistring::toFloat/Double/LDouble precise fixes
This commit is contained in:
@@ -3,7 +3,7 @@ cmake_policy(SET CMP0017 NEW) # need include() with .cmake
|
|||||||
project(PIP)
|
project(PIP)
|
||||||
set(PIP_MAJOR 3)
|
set(PIP_MAJOR 3)
|
||||||
set(PIP_MINOR 2)
|
set(PIP_MINOR 2)
|
||||||
set(PIP_REVISION 0)
|
set(PIP_REVISION 1)
|
||||||
set(PIP_SUFFIX )
|
set(PIP_SUFFIX )
|
||||||
set(PIP_COMPANY SHS)
|
set(PIP_COMPANY SHS)
|
||||||
set(PIP_DOMAIN org.SHS)
|
set(PIP_DOMAIN org.SHS)
|
||||||
|
|||||||
@@ -79,21 +79,18 @@ const float PIString::ElideCenter = .5f;
|
|||||||
const float PIString::ElideRight = 1.f;
|
const float PIString::ElideRight = 1.f;
|
||||||
|
|
||||||
|
|
||||||
inline float pow10(const int & e) {return powf(10.f, e);}
|
|
||||||
inline double pow10(const double & e) {return pow(10., e);}
|
|
||||||
inline ldouble pow10(const ldouble & e) {return powl(10.L, e);}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T toDecimal(const PIString & s) {
|
T toDecimal(const PIString & s) {
|
||||||
int part = 0, exp = 0;
|
int part = 0, exp = 0;
|
||||||
bool negative = false, negative_exp = false, err = false;
|
bool negative = false, negative_exp = false, err = false, has_digit = false;
|
||||||
T ret = 0., frac = 0., frac_delim = 10.;
|
T ret = 0., frac = 0., frac_delim = 1.;
|
||||||
for (const PIChar pc: s) {
|
for (const PIChar pc: s) {
|
||||||
char c = pc.toAscii();
|
char c = pc.toAscii();
|
||||||
switch (part) {
|
switch (part) {
|
||||||
case 0: // sign
|
case 0: // sign
|
||||||
if (pc.isSpace()) continue;
|
if (pc.isSpace()) continue;
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
|
has_digit = true;
|
||||||
ret = c - '0';
|
ret = c - '0';
|
||||||
part = 1;
|
part = 1;
|
||||||
continue;
|
continue;
|
||||||
@@ -115,6 +112,7 @@ T toDecimal(const PIString & s) {
|
|||||||
break;
|
break;
|
||||||
case 1: // integer
|
case 1: // integer
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
|
has_digit = true;
|
||||||
ret = ret * 10 + (c - '0');
|
ret = ret * 10 + (c - '0');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -122,7 +120,7 @@ T toDecimal(const PIString & s) {
|
|||||||
part = 2;
|
part = 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c == 'e' || c == 'E') {
|
if ((c == 'e' || c == 'E') && has_digit) {
|
||||||
part = 3;
|
part = 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -130,11 +128,12 @@ T toDecimal(const PIString & s) {
|
|||||||
break;
|
break;
|
||||||
case 2: // fractional
|
case 2: // fractional
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
frac += (c - '0') / frac_delim;
|
has_digit = true;
|
||||||
frac_delim *= 10;
|
frac = frac * 10 + (c - '0');
|
||||||
|
frac_delim *= 10.;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c == 'e' || c == 'E') {
|
if ((c == 'e' || c == 'E') && has_digit) {
|
||||||
part = 3;
|
part = 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -160,8 +159,9 @@ T toDecimal(const PIString & s) {
|
|||||||
}
|
}
|
||||||
if (err) break;
|
if (err) break;
|
||||||
}
|
}
|
||||||
|
frac /= frac_delim;
|
||||||
ret += frac;
|
ret += frac;
|
||||||
if (negative) ret = -ret;
|
if (negative && has_digit) ret = -ret;
|
||||||
if (exp > 0) {
|
if (exp > 0) {
|
||||||
if (negative_exp) ret /= pow10((T)exp);
|
if (negative_exp) ret /= pow10((T)exp);
|
||||||
else ret *= pow10((T)exp);
|
else ret *= pow10((T)exp);
|
||||||
|
|||||||
@@ -101,7 +101,12 @@ const double rad2deg = M_180_PI;
|
|||||||
inline int sign(const float & x) {return (x < 0.f) ? -1 : (x > 0.f ? 1 : 0);}
|
inline int sign(const float & x) {return (x < 0.f) ? -1 : (x > 0.f ? 1 : 0);}
|
||||||
inline int sign(const double & x) {return (x < 0. ) ? -1 : (x > 0. ? 1 : 0);}
|
inline int sign(const double & x) {return (x < 0. ) ? -1 : (x > 0. ? 1 : 0);}
|
||||||
inline int sign(const ldouble & x) {return (x < 0.L) ? -1 : (x > 0.L ? 1 : 0);}
|
inline int sign(const ldouble & x) {return (x < 0.L) ? -1 : (x > 0.L ? 1 : 0);}
|
||||||
|
|
||||||
inline int pow2(const int p) {return 1 << p;}
|
inline int pow2(const int p) {return 1 << p;}
|
||||||
|
inline float pow10(const int & e) {return powf(10.f, e);}
|
||||||
|
inline double pow10(const double & e) {return pow(10., e);}
|
||||||
|
inline ldouble pow10(const ldouble & e) {return powl(10.L, e);}
|
||||||
|
|
||||||
inline double sinc(const double & v) {if (v == 0.) return 1.; double t = M_PI * v; return sin(t) / t;}
|
inline double sinc(const double & v) {if (v == 0.) return 1.; double t = M_PI * v; return sin(t) / t;}
|
||||||
|
|
||||||
PIP_EXPORT double piJ0(const double & v);
|
PIP_EXPORT double piJ0(const double & v);
|
||||||
|
|||||||
62
main.cpp
62
main.cpp
@@ -5,21 +5,18 @@
|
|||||||
|
|
||||||
using namespace PICoutManipulators;
|
using namespace PICoutManipulators;
|
||||||
|
|
||||||
inline float pow10(const int & e) {return powf(10.f, e);}
|
|
||||||
inline double pow10(const double & e) {return pow(10., e);}
|
|
||||||
inline ldouble pow10(const ldouble & e) {return powl(10.L, e);}
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T toDouble(const PIString & s) {
|
T toDecimal(const PIString & s) {
|
||||||
int part = 0;
|
int part = 0, exp = 0;
|
||||||
bool negative = false, negative_exp = false, err = false;
|
bool negative = false, negative_exp = false, err = false, has_digit = false;
|
||||||
T ret = 0., frac = 0., frac_delim = 10., exp = 0;
|
T ret = 0., frac = 0., frac_delim = 1.;
|
||||||
for (const PIChar pc: s) {
|
for (const PIChar pc: s) {
|
||||||
char c = pc.toAscii();
|
char c = pc.toAscii();
|
||||||
switch (part) {
|
switch (part) {
|
||||||
case 0: // sign
|
case 0: // sign
|
||||||
if (pc.isSpace()) continue;
|
if (pc.isSpace()) continue;
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
|
has_digit = true;
|
||||||
ret = c - '0';
|
ret = c - '0';
|
||||||
part = 1;
|
part = 1;
|
||||||
continue;
|
continue;
|
||||||
@@ -41,6 +38,7 @@ T toDouble(const PIString & s) {
|
|||||||
break;
|
break;
|
||||||
case 1: // integer
|
case 1: // integer
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
|
has_digit = true;
|
||||||
ret = ret * 10 + (c - '0');
|
ret = ret * 10 + (c - '0');
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -48,7 +46,7 @@ T toDouble(const PIString & s) {
|
|||||||
part = 2;
|
part = 2;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c == 'e' || c == 'E') {
|
if ((c == 'e' || c == 'E') && has_digit) {
|
||||||
part = 3;
|
part = 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -56,11 +54,14 @@ T toDouble(const PIString & s) {
|
|||||||
break;
|
break;
|
||||||
case 2: // fractional
|
case 2: // fractional
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
frac += (c - '0') / frac_delim;
|
has_digit = true;
|
||||||
frac_delim *= 10;
|
frac = frac * 10 + (c - '0');
|
||||||
|
frac_delim *= 10.;
|
||||||
|
//piCout << frac << frac_delim;
|
||||||
|
//printf("%.20f %.20f\n", frac, T(c - '0') / frac_delim);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (c == 'e' || c == 'E') {
|
if ((c == 'e' || c == 'E') && has_digit) {
|
||||||
part = 3;
|
part = 3;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -86,19 +87,23 @@ T toDouble(const PIString & s) {
|
|||||||
}
|
}
|
||||||
if (err) break;
|
if (err) break;
|
||||||
}
|
}
|
||||||
|
frac /= frac_delim;
|
||||||
ret += frac;
|
ret += frac;
|
||||||
if (negative) ret = -ret;
|
if (negative && has_digit) ret = -ret;
|
||||||
if (exp > 0) {
|
if (exp > 0) {
|
||||||
if (negative_exp) ret /= pow10(exp);
|
if (negative_exp) ret /= pow10((T)exp);
|
||||||
else ret *= pow10(exp);
|
else ret *= pow10((T)exp);
|
||||||
}
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void test(const PIString & s) {
|
inline void test(const PIString & s) {
|
||||||
double av = toDouble<double>(s);
|
double av = atof(s.dataAscii());
|
||||||
double v = s.toDouble();
|
double v = toDecimal<double>(s);
|
||||||
|
printf("\n");
|
||||||
piCout << s << "=" << v << av;
|
piCout << s << "=" << v << av;
|
||||||
|
printf("atof = %.20f\n", av);
|
||||||
|
printf(" PIP = %.20f\n", v);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char * argv[]) {
|
int main(int argc, char * argv[]) {
|
||||||
@@ -139,27 +144,32 @@ int main(int argc, char * argv[]) {
|
|||||||
test("+E2");
|
test("+E2");
|
||||||
test("nan");
|
test("nan");
|
||||||
test("inf");*/
|
test("inf");*/
|
||||||
test("1.23");
|
test("-");
|
||||||
test("1,23");
|
test("-0");
|
||||||
test(".23");
|
test("-.");
|
||||||
test(",23");
|
test("-.0");
|
||||||
|
test(".23456123456789987654");
|
||||||
|
test("-E+100");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
PITimeMeasurer tm;
|
PITimeMeasurer tm;
|
||||||
PIString s("1E+600");
|
PIString s("1.23456789");
|
||||||
int cnt = 1000000;
|
int cnt = 10000000;
|
||||||
int el_o = 0, el_n = 0;
|
int el_o = 0, el_n = 0;
|
||||||
ldouble v = 0.;
|
double v = 0.;
|
||||||
NO_UNUSED(v);
|
NO_UNUSED(v);
|
||||||
|
|
||||||
tm.reset();
|
tm.reset();
|
||||||
piForTimes (cnt) {
|
piForTimes (cnt) {
|
||||||
v = s.toLDouble();
|
v = s.toDouble();
|
||||||
}
|
}
|
||||||
el_o = tm.elapsed_u();
|
el_o = tm.elapsed_u();
|
||||||
piCout << v << el_o;
|
piCout << v << el_o;
|
||||||
|
|
||||||
tm.reset();
|
tm.reset();
|
||||||
piForTimes (cnt) {
|
piForTimes (cnt) {
|
||||||
v = toDouble<ldouble>(s);
|
v = toDecimal<double>(s);
|
||||||
}
|
}
|
||||||
el_n = tm.elapsed_u();
|
el_n = tm.elapsed_u();
|
||||||
piCout << v << el_n;
|
piCout << v << el_n;
|
||||||
|
|||||||
Reference in New Issue
Block a user