mirror of
https://github.com/sqlite/sqlite.git
synced 2025-11-11 01:42:22 +03:00
Experiments with a new algorithm for converting ieee-754 binary64 numbers
into decimal. FossilOrigin-Name: e923405e448385085224f9289991b303d86b02763535ea77d6fcee98ba6fc1f2
This commit is contained in:
63
src/util.c
63
src/util.c
@@ -928,6 +928,69 @@ int sqlite3Atoi(const char *z){
|
||||
return x;
|
||||
}
|
||||
|
||||
/*
|
||||
** Decode a floating-point value into an approximate decimal
|
||||
** representation.
|
||||
*/
|
||||
void sqlite3FpDecode(FpDecode *p, double r){
|
||||
int i;
|
||||
u64 v;
|
||||
int e, exp = 0;
|
||||
if( r<0.0 ){
|
||||
p->sign = '-';
|
||||
r = -r;
|
||||
}else if( r==0.0 ){
|
||||
p->sign = '+';
|
||||
p->n = 1;
|
||||
p->iDP = 1;
|
||||
p->z[0] = '0';
|
||||
return;
|
||||
}else{
|
||||
p->sign = '+';
|
||||
}
|
||||
memcpy(&v,&r,8);
|
||||
e = v>>52;
|
||||
if( e==0x7ff ){
|
||||
if( v==0x7ff0000000000000L ){
|
||||
p->isInf = 1;
|
||||
p->isNan = 0;
|
||||
p->z[0] = 'I';
|
||||
p->z[1] = 'n';
|
||||
p->z[2] = 'f';
|
||||
}else{
|
||||
p->isInf = 0;
|
||||
p->isNan = 1;
|
||||
p->z[0] = 'N';
|
||||
p->z[1] = 'a';
|
||||
p->z[2] = 'N';
|
||||
}
|
||||
p->n = 3;
|
||||
p->iDP = 3;
|
||||
return;
|
||||
}
|
||||
/* At this point, r is positive (non-zero) and is not Inf or NaN.
|
||||
** The strategy is to multiple or divide r by powers of 10 until
|
||||
** it is in between 1.0e+17 and 1.0e+19. Then convert r into
|
||||
** an unsigned 64-bit integer v, and extract digits from v.
|
||||
*/
|
||||
if( r>=1.0e+19 ){
|
||||
while( r>=1.0e+119 ){ exp+=100; r /= 1.0e+100; }
|
||||
while( r>=1.0e+29 ){ exp+=10; r /= 1.0e+10; }
|
||||
while( r>=1.0e+19 ){ exp++; r /= 10.0; }
|
||||
}else if( r<1.0e+17 ){
|
||||
while( r<1.0e-97 ){ exp-=100; r *= 1.0e+100; }
|
||||
while( r<1.0e+07 ){ exp-=10; r *= 1.0e+10; }
|
||||
while( r<1.0e+17 ){ exp--; r *= 10.0; }
|
||||
}
|
||||
v = (u64)r;
|
||||
i = sizeof(p->z);
|
||||
while( v ){ p->z[i--] = (v%10) + '0'; v /= 10; }
|
||||
p->n = sizeof(p->z) - i;
|
||||
p->iDP = p->n + exp;
|
||||
memmove(p->z, &p->z[i+1], p->n);
|
||||
while( p->n>0 && p->z[p->n-1]=='0' ){ p->n--; }
|
||||
}
|
||||
|
||||
/*
|
||||
** Try to convert z into an unsigned 32-bit integer. Return true on
|
||||
** success and false if there is an error.
|
||||
|
||||
Reference in New Issue
Block a user