When using the find dialog of the data editor, previously a numeric value
was compared exactly on it's underlying representation (a IEEE754 double
precision float). This is problematic, because most such floats cannot
be precisely represented in a decimal format, and even if they can be, the
precision required might well exceed that displayed in the data editor.
This change rounds both the reference and the comparand to the number of
decimal places indicated by the variable's print format.
Changes from 1.2.0 to 1.3.0:
Changes from 1.2.0 to 1.3.0:
+ * The Find dialog box, when searching for numeric values, will match only
+ to the precision of the variable's print format. This avoids behaviour
+ which is suprising to some users.
+
* PSPP now supports the SPSS viewer (.spv) format that SPSS 16 and later
use to save the contents of its output editor:
* PSPP now supports the SPSS viewer (.spv) format that SPSS 16 and later
use to save the contents of its output editor:
#include <regex.h>
#include <stdlib.h>
#include <sys/types.h>
#include <regex.h>
#include <stdlib.h>
#include <sys/types.h>
#include "data/data-in.h"
#include "data/datasheet.h"
#include "data/data-in.h"
#include "data/datasheet.h"
-/* A comparator which operates on the unadulterated union values */
-struct value_comparator
+/* A comparator which operates on the numerical values,
+ rounded to the number of decimal places indicated by
+ the variable's format. */
+struct numeric_comparator
{
struct comparator parent;
{
struct comparator parent;
};
/* A comparator which matches string values or parts thereof */
};
/* A comparator which matches string values or parts thereof */
value_compare (const struct comparator *cmptr,
const union value *v)
{
value_compare (const struct comparator *cmptr,
const union value *v)
{
- const struct value_comparator *vc = (const struct value_comparator *) cmptr;
- return 0 == value_compare_3way (v, &vc->pattern, var_get_width (cmptr->var));
+ const struct numeric_comparator *nc = (const struct numeric_comparator *) cmptr;
+ const struct fmt_spec *fs = var_get_print_format (cmptr->var);
+
+ double c = nearbyint (v->f * exp10 (fs->d));
+
+ return c == nc->rounded_ref;
-static void
-cmptr_value_destroy (struct comparator *cmptr)
-{
- struct value_comparator *vc
- = UP_CAST (cmptr, struct value_comparator, parent);
- value_destroy (&vc->pattern, var_get_width (cmptr->var));
-}
-
-
static struct comparator *
static struct comparator *
-value_comparator_create (const struct variable *var, const char *target)
+numeric_comparator_create (const struct variable *var, const char *target)
- struct value_comparator *vc = xzalloc (sizeof (*vc));
- struct comparator *cmptr = &vc->parent;
+ struct numeric_comparator *nc = xzalloc (sizeof (*nc));
+ struct comparator *cmptr = &nc->parent;
cmptr->flags = 0;
cmptr->var = var;
cmptr->flags = 0;
cmptr->var = var;
- cmptr->compare = value_compare ;
- cmptr->destroy = cmptr_value_destroy;
+ cmptr->compare = value_compare;
+ const struct fmt_spec *fs = var_get_write_format (var);
- text_to_value (target, var, &vc->pattern);
+ union value val;
+ text_to_value (target, var, &val);
+ nc->rounded_ref = nearbyint (val.f * exp10 (fs->d));
+ value_destroy (&val, var_get_width (var));
if (flags & (STR_CMP_SUBSTR | STR_CMP_LABELS))
return string_comparator_create (var, str, flags);
if (flags & (STR_CMP_SUBSTR | STR_CMP_LABELS))
return string_comparator_create (var, str, flags);
- return value_comparator_create (var, str);
+ return numeric_comparator_create (var, str);