[prev in list] [next in list] [prev in thread] [next in thread]
List: kde-commits
Subject: kdeutils/kcalc
From: Klaus Niederkrüger <kniederk () mi ! uni-koeln ! de>
Date: 2005-01-24 0:39:43
Message-ID: 20050124003943.F33051BA82 () office ! kde ! org
[Download RAW message or body]
CVS commit by kniederk:
I hope this fixes the rounding problem. Please control this patch if you have time \
(and know about floating points). Thanks
M +29 -14 kcalc_core.cpp 1.97
M +3 -1 kcalctype.h 1.23
--- kdeutils/kcalc/kcalc_core.cpp #1.96:1.97
@@ -213,11 +213,19 @@ static CALCAMNT ExecAdd(CALCAMNT left_op
// printf("ExecAdd\n");
CALCAMNT tmp_result = left_op + right_op;
- // Set result to zero, when smaller than FPU-precision
- CALCAMNT tmp_divisor = FABS(left_op) + FABS(right_op);
- if (tmp_divisor != 0L &&
- FABS(tmp_result)/tmp_divisor > 2*CALCAMNT_EPSILON)
- return tmp_result;
- else
- return 0L;
+
+ // When operating with floating point numbers the following
+ // effect can happen: 1.0000001 + (-1.0) gives 1.0000232e-6
+ // instead of 1e-6. This looks very bad on a calculator (to
+ // the unexperienced eye). Hence we round in this case.
+ CALCAMNT max_precision = (FABS(left_op) + FABS(right_op))
+ * CALCAMNT_EPSILON;
+ // we want to round to decimal digits, hence we need to find
+ // the number of valid digits
+ CALCAMNT digits = 1;
+ while (digits > max_precision)
+ digits *= 0.1L;
+ digits *= 100.0L; // this number is experimental
+
+ return digits * ROUND(tmp_result/digits);
}
@@ -226,11 +234,18 @@ static CALCAMNT ExecSubtract(CALCAMNT le
// printf("ExecSubtract\n");
CALCAMNT tmp_result = left_op - right_op;
- // Set result to zero, when smaller than FPU-precision
- CALCAMNT tmp_divisor = FABS(left_op) + FABS(right_op);
- if (tmp_divisor != 0L &&
- FABS(tmp_result)/tmp_divisor > 2*CALCAMNT_EPSILON)
- return tmp_result;
- else
- return 0L;
+ // When operating with floating point numbers the following
+ // effect can happen: 1.0000001 + (-1.0) gives 1.0000232e-6
+ // instead of 1e-6. This looks very bad on a calculator (to
+ // the unexperienced eye). Hence we round in this case.
+ CALCAMNT max_precision = (FABS(left_op) + FABS(right_op))
+ * CALCAMNT_EPSILON;
+ // we want to round to decimal digits, hence we need to find
+ // the number of valid digits
+ CALCAMNT digits = 1;
+ while (digits > max_precision)
+ digits *= 0.1L;
+ digits *= 100.0L; // this number is experimental
+
+ return digits * ROUND(tmp_result/digits);
}
--- kdeutils/kcalc/kcalctype.h #1.22:1.23
@@ -74,4 +74,5 @@
#define ISINF(X) isinfl(X)
#define STRTOD(X,Y) strtold(X,Y)
+ #define ROUND(X) roundl(X)
#define CALCAMNT_EPSILON LDBL_EPSILON
#else
@@ -99,4 +100,5 @@
#define ISINF(X) isinf(X)
#define STRTOD(X,Y) strtod(X,Y)
+ #define ROUND(X) round(X)
#define CALCAMNT_EPSILON DBL_EPSILON
#endif
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic