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.

Reply via email to