digitalmars.D - Floating-point zeros not caught by comparison
- JonathanC (23/23) Feb 01 2007 I'm having a problem with an if statement not catching some floating-poi...
- Frits van Bommel (70/96) Feb 01 2007 So you're removing the zeros by copying the part of the array after
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
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