Great. thanks. This should remove any remaining doubts (if there were any). Btw: if you want to play with doubles have a look at doubles.h (recently checked in). It gives easy access to significands and exponents. // florian
On Tue, Mar 23, 2010 at 12:36 PM, Sergey Ryazanov <[email protected]> wrote: > > 4.45014771701440202508199667279499186358524265859260511351695091228726223124931264069530541271189424317838013700808305231545782515453032382772695923684574304409936197089118747150815050941806048037511737832041185193533879641611520514874130831632725201246060231058690536206311752656217652146466431814205051640436322226680064743260560117135282915796422274554896821334728738317548403413978098469341510556195293821919814730032341053661708792231510873354131880491105553390278848567812190177545006298062245710295816371174594568773301103242116891776567137054973871082078224775842509670618916870627821633352993761380751142008862499795052791018709663463944015644907297315659352441231715398102212132212018470035807616260163568645811358486831521563686919762403704226016998291015625000000000000000000000000000000000e-308 > > (768 significant digits). > > #include <math.h> > #include <assert.h> > #include <stdio.h> > > int main() { > double x = (pow(2, 52) - 1) * 2.0 + 1.0; > assert(x != x - 1.0); > > double mind = 1 * pow(2, -1023) * pow(2, -51); > assert(mind != 0.0); > assert(mind / 2 == 0.0); > > long double a = mind * x; > long double b = mind * (x - 1); > > printf("%.800Le\n", (a + b) / 2); > > return 0; > } > > On Tue, Mar 23, 2010 at 12:27 PM, Florian Loitsch <[email protected]>wrote: > >> It's a pity that most of the time more than 700 bytes on the stack are >> wasted, but I don't see any easier solution. I agree with Erik (offline >> discussion) that ~780 bytes on the stack should not be a big issue since the >> memory is not initialized and we are not calling this function recursively. >> I vote for allocating the big buffer on the stack. >> btw: it would be nice to have one example of a halfway-case with 771 >> digits. (Note that sprintf "%.771e" gives a number with 771 precision >> digits). >> // florian >> >> On Mon, Mar 22, 2010 at 7:53 PM, Sergey Ryazanov <[email protected]>wrote: >> >>> It seems that strtod rounds a decimal to a closest number >>> representable in double ("24414062505131250" parses as >>> 24414062505131248 and "24414062505131250.0.....01" 24414062505131252). >>> As I get from GNU source code it uses "multipercision numbers" for >>> exact representation of numbers. >>> >>> Any double is representable as d*2^p where 0 <= d < 2^53 and ... < p >>> <= -1074 (considering subnormal numbers). Any positive double x has >>> exact decimal representation: >>> 1) if 0 < x < 1: not more than ~770 significant digits (2^53 * 5^1074) >>> 2) 2^53 < x < DBL_MAX: not more than 308 significant digits since it's >>> an integer and DBL_MAX ≈ 1.79769 × 10^308. >>> 3) 1 < x < 2^53: not more than 60 significant digits. >>> (significant digits doesn't include leading and trailing zeros). >>> >>> Let's we have a decimal with more than 770 significant digits. We want >>> to find a double closest to our number. Dropping other digits (as well >>> as changing them to any other digits) would give us right result >>> unless our number lays exactly between 2 adjacent doubles. Mean of 2 >>> adjacent doubles may have not more that 771 digits (all other would be >>> zoros). If the first digits of our number are equal to the digits of >>> that number the result of rounding would depend on if the rest of >>> digits are zeros. >>> >>> So conclusion is following: If we preserve at least 771 significant >>> digits and replace any nonzero tail by '1' we would never change >>> behavior of strtod. >>> >>> >>> On Sat, Mar 20, 2010 at 7:56 PM, <[email protected]> wrote: >>> > I will discuss the >>> > 100000000000000000000000.0000000000000000000000000000000000000000000001 >>> > issue >>> > with the V8 team on monday. >>> > The way I see it we have two options: >>> > 1. Follow ECMA-262 and round down, thus being incompatible with older >>> > versions. >>> > 2. Fallback to a more expensive reading when there are more than 20 >>> digits. >>> > >>> > Pros/Cons for 1: >>> > Pro: Basically nothing to do. That's what we have now. >>> > Cons: Incompatible and we might numbers the "wrong" way. On the other >>> hand >>> > these >>> > numbers have to be written by hand (toString/toExponential/toFixed will >>> > never >>> > produce a number that would make such problems). Therefore they are >>> > extremely >>> > rare. >>> > >>> > Pros/Cons for 2: >>> > Pro: Compatible with older variants of V8. Reading is correct. Might >>> > slightly >>> > simplify the fast case: the exponent would need to be in range -999 to >>> 999. >>> > Cons: we would need to keep/add a fallback method. Maybe a template >>> taking >>> > either a fixed-size buffer or a dynamic vector would do the trick, >>> though. >>> > >>> > >>> > >>> > http://codereview.chromium.org/1096002/diff/3002/4003 >>> > File src/conversions.cc (right): >>> > >>> > http://codereview.chromium.org/1096002/diff/3002/4003#newcode109 >>> > src/conversions.cc:109: bool operator != (EndMarker const& m) const { >>> > return !(*this == m); } >>> > On 2010/03/19 15:46:12, SeRya wrote: >>> >> >>> >> On 2010/03/18 20:34:22, Erik Corry wrote: >>> >> > Some funky C++ here :-). return !end_; seems simpler, but perhaps >>> > >>> > this is >>> >> >>> >> > somehow better? >>> > >>> >> Just a canonical form of != which simplifies maintenance (IMHO). >>> > >>> > I'm with Erik here. >>> > I still don't understand how this actually types. (Although I'm by no >>> > means a C++ expert). >>> > Also operator-overloading should be rare in Google code. >>> > Why not Peek(), AtEnd(), etc? >>> > This said, I'm not very familiar with V8 coding practices. >>> > >>> > http://codereview.chromium.org/1096002/diff/3002/4003#newcode496 >>> > src/conversions.cc:496: const int max_exponent = INT_MAX / 2; >>> > On 2010/03/19 15:46:12, SeRya wrote: >>> >> >>> >> On 2010/03/19 13:39:43, Florian Loitsch wrote: >>> >> > This seems to be too complicated. A decimal number without leading >>> > >>> > 0s may only >>> >> >>> >> > have a decimal exponent of ~-400 to ~+400 before ending up being >>> > >>> > infinite or >>> >> >>> >> 0. >>> > >>> >> 1<1000 zeros>e-1000 == 1. >>> > >>> > Right you are. >>> > >>> > http://codereview.chromium.org/1096002/diff/3002/4003#newcode519 >>> > src/conversions.cc:519: if (exponent != 0) { >>> > On 2010/03/19 15:46:12, SeRya wrote: >>> >> >>> >> On 2010/03/19 13:39:43, Florian Loitsch wrote: >>> >> > not that it really matters, but you could copy the exponent >>> > >>> > characters while >>> >> >>> >> > reading them, and just stop after 4 digits. >>> >> > This way you could avoid this part here. >>> > >>> >> It would mean another chunk of code that which drop leading zeros and >>> > >>> > check for >>> >> >>> >> junk tail. I'd prefer to simplify for now and may be add this >>> > >>> > optimization >>> >> >>> >> later. >>> > >>> > my comment was based on the assumption that the read exponent was in >>> > range -400 to +400. So disregard it. >>> > >>> > http://codereview.chromium.org/1096002/diff/21004/27003#newcode298 >>> > src/conversions.cc:298: // 1. currnet == end (other ops are not >>> > allowed), current != end. >>> > Are we sure there is at least one character? >>> > If yes assert it. >>> > If not, and it is legal to access current[0] of empty string, explain. >>> > >>> > http://codereview.chromium.org/1096002/diff/21004/27003#newcode330 >>> > src/conversions.cc:330: buffer[buffer_pos++] = '-'; >>> > It might make sense to move the hexadecimal reading into a separate >>> > function. >>> > >>> > http://codereview.chromium.org/1096002/diff/21004/27003#newcode405 >>> > src/conversions.cc:405: if (current == end) return signed_zero; >>> > I think it makes more sense to structure as follows: >>> > if (current == end) { >>> > if (significant_digits == 0 && !leading_zero) { >>> > // String was ".". >>> > return JUNK_STRING_VALUE; >>> > } else { >>> > goto parsing_done; >>> > } >>> > } >>> > if (significant_digits == 0) { >>> > octal = false; >>> > ... >>> > } >>> > >>> > http://codereview.chromium.org/1096002/diff/21004/27003#newcode451 >>> > src/conversions.cc:451: } >>> > How should "123e" be parsed when "trailing junk is enabled? >>> > as "123" or as JUNK_STRING_VALUE? >>> > If it's the latter, then this is fine. >>> > >>> > http://codereview.chromium.org/1096002/diff/21004/27003#newcode456 >>> > src/conversions.cc:456: ++current; >>> > As before: should 123e+ be parsed as 123 or JUNK_STRING_VALUE when >>> > trailing junk is enabled. >>> > >>> > http://codereview.chromium.org/1096002 >>> > >>> >> >> > -- v8-dev mailing list [email protected] http://groups.google.com/group/v8-dev To unsubscribe from this group, send email to v8-dev+unsubscribegooglegroups.com or reply to this email with the words "REMOVE ME" as the subject.
