jeroenes has asked for the wisdom of the Perl Monks concerning the following question:

Here I have a strange problem, and a workaround. I don't know whether I have a bug in my code, or a bug in something else (my eye for example).

The code itself serves some specialistic purpose, which has to do something with event-counting and autocorrelation. It falls beyond the scope of this question, so I skip that for now.

The core of my problem lies in the following line:

$left_idx++ if $store->[$left_idx] < $start;
This will sometimes falsely evaluate to false. I tracked down the values, and it only failed in 7 out of a range of 1000 used values. A workaround was quickly found:
# $left_idx++ if $store->[$left_idx] < $start; #normal $left_idx++ if ($store->[$left_idx]+1) < ($start+1); #0.6 bug workar +ound
Just add 1 to each side of the equation, and everything works fine. I traced down some numbers, to give you an idea:
1.6 [8]: 0.8 1 1.2 1.4 1.8 2 2.2 + 2.4 2.6 2.2 [11]: 1.4 1.6 1.8 2 2.4 2.6 2.8 + 3 3.2 4.4 [22]: 3.6 3.8 4 4.2 4.6 4.8 5 + 5.2 5.4 8.8 [44]: 8 8.2 8.4 8.6 9 9.2 9.4 + 9.6 9.8 16.6 [83]: 15.8 16 16.2 16.4 16.8 17 17.2 + 17.4 17.6 32.2 [161]: 31.4 31.6 31.8 32 32.4 32.6 32.8 + 33 33.2 64.4 [322]: 63.6 63.8 64 64.2 64.6 64.8 65 + 65.2 65.4
I also saved part of my debugging session comparing the values:
DB<25> x ($store->[3]) == $start 0 '' DB<26> x ($store->[3]+0) == $start 0 '' DB<27> x $start 0 0.6 DB<28> x $store->[3] 0 0.6 DB<29> x 0.6 == $start 0 '' DB<30> x $start == 0.6 0 '' DB<31> x 0.6 == 0.6 0 1 DB<32> x ($store->[3]+0) == ($start+0) 0 '' DB<33> x ($store->[3]+1) == ($start+1) 0 1
Pretty strange, isn't it? OK, now I give you the complete code (in a package) and code to call it:
Edit 2001-04-06 by tye to comment out long code listing. To see the code, view the HTML source for this page.

Please shoot, point me to my mistakes, but most of all, please explain me what's going on here!

Thanks a lot,

Jeroen
"We are not alone"(FZ)

Replies are listed 'Best First'.
Re: Comparison misses a true in *some* cases
by merlyn (Sage) on Apr 06, 2001 at 19:33 UTC
    I didn't read everything, but I see floating point numbers, and I see comparisons. Perhaps you're not aware of the "approximation" factor in floating point numbers, where apparently obvious things like (2 / 0.1) == 20 are not necessarily true. I'll keep reading the thread to see if it's something else, but I'd put a bet on this one.

    -- Randal L. Schwartz, Perl hacker

      Yes, that is the problem.

      DB<27> x $start 0 0.6 DB<28> x $store->[3] 0 0.6 DB<29> x 0.6 == $start 0 ''
      jeroenes, repeat the above and do "x $start-0.6" and you may be enlightened.

      Update: So we all can take part in the fun:

      DB<1> $x=0.6 DB<2> x ($l,$h)=unpack"L*",pack"d",$x 0 858993459 1 1071854387 DB<3> x $y=unpack"d",pack"L*",$l+1,$h 0 0.6 DB<4> x $z=unpack"d",pack"L*",$l-1,$h 0 0.6 DB<5> x $y-$x 0 '1.11022302462516e-016' DB<6> x $x-$z 0 '1.11022302462516e-016' DB<7> x $y-$z 0 '2.22044604925031e-016' DB<8> x unpack"d",pack"L*",$l-4,$h 0 0.6 DB<9> x unpack"d",pack"L*",$l-5,$h 0 0.599999999999999 DB<10> x unpack"d",pack"L*",$l+4,$h 0 0.6 DB<11> x unpack"d",pack"L*",$l+5,$h 0 0.600000000000001
      Welcome to floating point.

              - tye (but my friends call me "Tye")
        merlyn, tye and tilly (in CB): thanks a lot. tye especially thanks for the warm welcome ;-). Your debug-lines clear up a lot, I must say.

        This whole thread is a nice example of a testing procedure gone that evokes it's own problems. My real-world data will, by definition, never repeat. Accidently, some datapoints may have an exact interval of one second, but that chance will be neglectable. (1 out of 1000 or less, I estimate)

        I will be on guard for the floating point arrhythmic from now on.

        Jeroen
        "We are not alone"(FZ)

Re: Comparison misses a true in *some* cases
by busunsl (Vicar) on Apr 06, 2001 at 19:27 UTC
    AFAIK is the order of evaluation not predictable, that is in
    $left_idx++ if $store->[$left_idx] < $start;
    $left_idx might be increased before or after the if.
      No, I'm afraid you're wrong. That would be a terribly bad bug. In an if statement, the condition ($store->[$left_idx] < $start) MUST be evaluated before the execution of that which DEPENDS on the condition ($left_idx++).

      japhy -- Perl and Regex Hacker
      Well, I never had problems with that before. But even if this is the case, that wouldn't explain the behavior nor the workaround.

      Jeroen
      "We are not alone"(FZ)