Floating-point zeros not caught by comparison

Frits van Bommel fvbommel at REMwOVExCAPSs.nl
Thu Feb 1 11:11:28 PST 2007


JonathanC wrote:
> I'm having a problem with an if statement not catching some floating-point zeros. I know that there are 9 values in the array, but only 7 are found by the if and outputted by the debug statement. If I remove the if statement and the code in its block, all 9 of the zeros are printed by the debug statement.
> 
> Does anyone have any idea what might be the problem?
> 
> Thanks,
> JonathanC
> 
> Code:
> ------------------------------------------------------------------------------------------
>     uint zeros = 0;
>     real test = .01;
>     uint size = X.Rows;
>     for (uint i = 0; i < size; i++)
>     {
>         real r = X.Data[i];
>         debug (calcXHI) writefln("i:", i, ", r:", r);
>         if (std.math.abs(r) <= test)
>         {
>             zeros++;
>             size--;
>             for (j = i + 1; j < size; j++)
>             {
>                 X.Data[j - 1] = X.Data[j];
>             }
>         }
>     }

So you're removing the zeros by copying the part of the array after 
every zero one place forward?

First of all, you should probably decrease 'size' after the inner loop 
to preserve the last element.

It looks like you forgot to also decrease i when you do that, so if 
there are two consecutive zeros you miss the second one.

So that gets you this (modified to make X a regular array):
---
import std.stdio;
import std.math;

void main() {
     float[] X = [ 0f, 1, 2, 0, 0, 3, 4, 5, 0, 6, 7, 0, 0, 8];
     writefln(X);

     uint zeros = 0;
     real test = .01;
     uint size = X.length;
     for (uint i = 0; i < size; i++)
     {
         real r = X[i];
         debug (calcXHI) writefln("i:", i, ", r:", r);
         if (std.math.abs(r) <= test)
         {
             zeros++;
             for (size_t j = i + 1; j < size; j++)
             {
                 X[j - 1] = X[j];
             }
             size--;
         i--;
         }
     }

     writefln(X[0 .. size]);
}
---

Also, this code might be more efficient: (will only copy values once at 
most)
---
import std.stdio;
import std.math;

void main() {
     float[] X = [ 0f, 1, 2, 0, 0, 3, 4, 5, 0, 6, 7, 0, 0, 8];
     writefln(X);

     uint zeros = 0;
     real test = .01;
     uint size = X.length;
     // k is the next element to inspect.
     // i is the next location to copy to.
     // loop ends when k >= X.length (not size) because later elements
     // aren't moved anymore.
     for (uint i = 0, k = 0; k < X.length; k++)
     {
         real r = X[k];
         debug (calcXHI) writefln("i:", i, ", k:", k, ", r:", r);
         if (std.math.abs(r) <= test)
         {
             zeros++;
             size--;
         }
         else
         {
             // copy next element (can be conditional on (zeros > 0) or,
             // if you prefer,  (i != k)
             X[i] = r;
             i++;
         }
     }

     writefln(X[0 .. size]);
}
---



More information about the Digitalmars-d mailing list