www.digitalmars.com         C & C++   DMDScript  

digitalmars.D - Floating-point zeros not caught by comparison

reply JonathanC <jcrapuchettes gamil.com> writes:
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];
            }
        }
    }
Feb 01 2007
parent Frits van Bommel <fvbommel REMwOVExCAPSs.nl> writes:
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]); } ---
Feb 01 2007