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;
