In string_to_num() in src/string.c, f = f * sign * pow(10.0, exponent); /* ugly, oh yeah */
Which in this case translates to 12.0*-1*0.1 which is -1.2000...2 != -1.2.
I replaced this bit of code from a block I found in mysql. I only tested this
on linux, but it seems to do the trick. See attached.
Leopold Toetsch wrote:
Simon Glover <[EMAIL PROTECTED]> wrote:
This code:
new P0, .PerlNum
set P0, -1.2
new P1, .PerlString
set P1, "-1.2"
eq_num P0, P1, OK
print "not "
OK: print "ok\n"
end
[And yes, I'm well aware of the problems inherent in doing floating point
comparisons.
Breakpoint 1, Parrot_PerlNum_cmp_num (interpreter=0x82654f0, pmc=0x40305850, value=0x40305838) at perlnum.c:301 301 diff = PMC_num_val(pmc) - VTABLE_get_number(interpreter, value); (gdb) n 302 return diff > 0 ? 1 : diff < 0 ? -1 : 0; (gdb) p diff $1 = 2.2204460492503131e-16 (gdb)
Simon
leo
*** tmp/parrot/src/string.c Sat Mar 6 03:00:06 2004 --- parrot/src/string.c Wed Mar 17 12:24:02 2004 *************** *** 1836,1844 **** int exp_sign = 0; INTVAL in_exp = 0; INTVAL in_number = 0; ! FLOATVAL exponent = 0; INTVAL fake_exponent = 0; INTVAL digit_family = 0; while (start < end) { UINTVAL c = s->encoding->decode(start); --- 1836,1845 ---- int exp_sign = 0; INTVAL in_exp = 0; INTVAL in_number = 0; ! INTVAL exponent = 0; INTVAL fake_exponent = 0; INTVAL digit_family = 0; + FLOATVAL exp_log=10.0, exp_val=1.0; while (start < end) { UINTVAL c = s->encoding->decode(start); *************** *** 1849,1855 **** if (df && df == digit_family) { if (in_exp) { ! exponent = exponent * 10 + s->type->get_digit(s->type,c); if (!exp_sign) { exp_sign = 1; } --- 1850,1856 ---- if (df && df == digit_family) { if (in_exp) { ! exponent = exponent + s->type->get_digit(s->type,c); if (!exp_sign) { exp_sign = 1; } *************** *** 1906,1912 **** exponent = fake_exponent + exponent * exp_sign; ! f = f * sign * pow(10.0, exponent); /* ugly, oh yeah */ } return f; --- 1907,1936 ---- exponent = fake_exponent + exponent * exp_sign; ! if(exponent < 0) { ! exponent = -exponent; ! exp_sign=-1; ! } ! ! for (;;) { ! if (exponent & 1) { ! exp_val *= exp_log; ! exponent--; ! } ! if (!exponent) ! break; ! exp_log *= exp_log; ! exponent >>= 1; ! } ! ! if(exp_sign < 0) ! f /= exp_val; ! else ! f *= exp_val; ! ! ! if(sign < 0) ! f = -f; } return f;