#include "support.h" double MyScanDouble(const char *p, const char **endptr) { const char *begin = p; while(*p && (byte)*p <= ' ') p++; bool neg = false; if(*p == '+' || *p == '-') neg = (*p++ == '-'); if((byte)(*p - '0') >= 10 && !(*p == *GetSystemDecimalSeparator() && (byte)(p[1] - '0') < 10)) { if(endptr) *endptr = begin; return Null; } double mantissa = 0; char c; int exp = 0; while((byte)(*p - '0') < 10) if((c = *p++) != '0') { if(exp) { mantissa *= ipow10(exp); exp = 0; } mantissa = 10 * mantissa + c - '0'; } else exp++; int raise = exp; if(*p == *GetSystemDecimalSeparator()) // decimal part while((byte)((c = *++p) - '0') < 10) if(c != '0') { if(raise) { mantissa *= ipow10(raise); exp -= raise; raise = 0; } exp--; mantissa = 10 * mantissa + c - '0'; } else raise++; if(*p == 'E' || *p == 'e') { // exponent int vexp = ScanInt(p + 1, endptr); if(!IsNull(vexp)) exp += vexp; } else if(endptr) *endptr = p; if(exp) { double e = ipow10(tabs(exp)); mantissa = (exp > 0 ? mantissa * e : mantissa / e); } return neg ? -mantissa : mantissa; } double MyScanDouble(const wchar *p, const wchar **endptr) { const wchar *begin = p; while(*p && *p <= ' ') p++; bool neg = false; if(*p == '+' || *p == '-') neg = (*p++ == '-'); if((unsigned)(*p - '0') >= 10) { if(endptr) *endptr = begin; return Null; } double mantissa = 0; wchar c; int exp = 0; while((unsigned)(*p - '0') < 10) if((c = *p++) != '0') { if(exp) { mantissa *= ipow10(exp); exp = 0; } mantissa = 10 * mantissa + c - '0'; } else exp++; int raise = exp; if(*p == *GetSystemDecimalSeparator()) // decimal part while((unsigned)((c = *++p) - '0') < 10) if(c != '0') { if(raise) { mantissa *= ipow10(raise); exp -= raise; raise = 0; } exp--; mantissa = 10 * mantissa + c - '0'; } else raise++; if(*p == 'E' || *p == 'e') { // exponent int vexp = ScanInt(p + 1, endptr); if(!IsNull(vexp)) exp += vexp; } else if(endptr) *endptr = p; if(exp) { double e = ipow10(tabs(exp)); mantissa = (exp > 0 ? mantissa * e : mantissa / e); } return neg ? -mantissa : mantissa; } String MyFormatDouble(double d, int digits, int flags, int pad_exp) { if(IsNull(d)) return Null; double ad = fabs(d); bool is_exp = (flags & FD_EXP); if(!(flags & FD_FIX)) { is_exp = ad && (ad <= 1e-15 || ad >= 1e15); if(flags & FD_REL) { double bd = ipow10(2 * digits); if(ad && (ad * bd <= 1 || ad >= bd)) is_exp = true; } } if(is_exp) return MyFormatDoubleExp(d, digits, flags, pad_exp); else return MyFormatDoubleFix(d, digits, flags); } String MyFormatDoubleFix(double d, int digits, int flags) { if(IsNull(d)) return Null; int exp; String dig = FormatDoubleDigits(d, digits, flags, exp); if(flags & FD_REL) digits = max(0, digits - Nvl(exp, 0) - 1); String out; if(flags & FD_SIGN || d < 0 && !IsNull(exp)) out.Cat(d >= 0 ? '+' : '-'); if(IsNull(exp) || exp < -digits) { out.Cat('0'); if(flags & FD_ZERO) { out.Cat(*GetSystemDecimalSeparator()); out.Cat('0', digits); } } else if(exp < 0) { out.Cat("0"); out.Cat(*GetSystemDecimalSeparator()); out.Cat('0', -1 - exp); int fill = digits + exp + 1; if(!(flags & FD_ZERO) || dig.GetLength() >= fill) out.Cat(dig, min(fill, dig.GetLength())); else { out.Cat(dig); out.Cat('0', fill - dig.GetLength()); } } else if(exp < dig.GetLength()) { out.Cat(dig, ++exp); if(digits > 0 && ((flags & FD_ZERO) || dig.GetLength() > exp)) { out.Cat(*GetSystemDecimalSeparator()); if(!(flags & FD_ZERO) || dig.GetLength() - exp >= digits) out.Cat(dig.Begin() + exp, min(dig.GetLength() - exp, digits)); else { out.Cat(dig.Begin() + exp, dig.GetLength() - exp); out.Cat('0', digits - (dig.GetLength() - exp)); } } } else { out.Cat(dig); out.Cat('0', exp - dig.GetLength() + 1); if(digits > 0 && (flags & FD_ZERO)) { out.Cat(*GetSystemDecimalSeparator()); out.Cat('0', digits); } } return out; } String MyFormatDoubleExp(double d, int digits, int flags, int fill_exp) { if(IsNull(d)) return Null; int exp; String dig = FormatDoubleDigits(d, digits, flags | FD_REL, exp); exp = Nvl(exp, 0); String out; if(flags & FD_SIGN || d < 0 && !IsNull(exp)) out.Cat(d >= 0 ? '+' : '-'); out.Cat(dig[0]); if(dig.GetLength() > 1) { out.Cat(*GetSystemDecimalSeparator()); out.Cat(dig.Begin() + 1, dig.GetLength() - 1); } out.Cat(flags & FD_CAP_E ? 'E' : 'e'); out.Cat(FormatIntDec(exp, fill_exp, '0', flags & FD_SIGN_EXP)); return out; }