Numeric comparisons

Post Reply
User avatar
E. Bartzokas
Posts: 114
Joined: Tue Feb 14, 2006 8:13 am
Location: Corinth, Greece

Numeric comparisons

Post by E. Bartzokas »

Hi all,
Either I got crazy, or something else is happening...
I have a problem with the 32-bit that does not exist in the 16-bit, or DOS.

To better describe the problem:

1. I have a database with four CHAR fields (width 20) that hold some numbers (amounts) with four decimals in them.

Example:
Soc.Security Medicare Withholding Total Amount
1172.0200 275.2700 839.0600 2291.3500

If I get the VAL() of each database field from the above, round them to 2 decimals, then add them up, I get the result 2291.35 (CORRECT) !!!

Now, the second record in the database contains these:
Soc.Security Medicare Withholding Total Amount
1019.5000 238.4400 679.9000 1937.8400

In my loops, I need to compare if the three first values of the fields, are equal to the Total Amount.

As I state above, the first example record results to .T. (equal).
The second record, and many more records (practically all of them are equal, if I add them up they match the total amount value, which notice that it is also of CHAR type in the field, converted to VAL(), and Rounded to 2 decimals, I get the same incorrect result (.F.), when I do the comparison.

Since I made the thought that either I'm too stressed from working too much, or getting too old, I wouldn't like to mention about having problems with FWH numeric comparisons.... thus, I copied the code from the 32-bit PRG and pasted it into a stand-alone PRG which I compiled in FW 16-bit, and another one in MS-DOS.

Both the 16-bit applications came up with .T. everywhere where they should be .T. of course. To make things easier, all the fields match the Total amount in the same record.

Now I am sitting down and do nothing further because this issue has driven me crazy. I have more than 30 years in the field, and am sure that there is nothing wrong with my code... simple things, that in addition, are working perfectly in the 16-bit environment.

Can some of my friends try to reproduce and verify that the above numbers, if read from a dbf stored as characters, do not match the total amount?

I would be grateful if I receive some answer(s).

Kind regards
Evans
ps. Sorry if the numbers don't show too nice above...
User avatar
Richard Chidiak
Posts: 946
Joined: Thu Oct 06, 2005 7:05 pm
Location: France
Contact:

Re: Numeric comparisons

Post by Richard Chidiak »

E. Bartzokas wrote:Hi all,
Either I got crazy, or something else is happening...
I have a problem with the 32-bit that does not exist in the 16-bit, or DOS.

To better describe the problem:

1. I have a database with four CHAR fields (width 20) that hold some numbers (amounts) with four decimals in them.

Example:
Soc.Security Medicare Withholding Total Amount
1172.0200 275.2700 839.0600 2291.3500

If I get the VAL() of each database field from the above, round them to 2 decimals, then add them up, I get the result 2291.35 (CORRECT) !!!

Now, the second record in the database contains these:
Soc.Security Medicare Withholding Total Amount
1019.5000 238.4400 679.9000 1937.8400

In my loops, I need to compare if the three first values of the fields, are equal to the Total Amount.

As I state above, the first example record results to .T. (equal).
The second record, and many more records (practically all of them are equal, if I add them up they match the total amount value, which notice that it is also of CHAR type in the field, converted to VAL(), and Rounded to 2 decimals, I get the same incorrect result (.F.), when I do the comparison.

Since I made the thought that either I'm too stressed from working too much, or getting too old, I wouldn't like to mention about having problems with FWH numeric comparisons.... thus, I copied the code from the 32-bit PRG and pasted it into a stand-alone PRG which I compiled in FW 16-bit, and another one in MS-DOS.

Both the 16-bit applications came up with .T. everywhere where they should be .T. of course. To make things easier, all the fields match the Total amount in the same record.

Now I am sitting down and do nothing further because this issue has driven me crazy. I have more than 30 years in the field, and am sure that there is nothing wrong with my code... simple things, that in addition, are working perfectly in the 16-bit environment.

Can some of my friends try to reproduce and verify that the above numbers, if read from a dbf stored as characters, do not match the total amount?

I would be grateful if I receive some answer(s).

Kind regards
Evans
ps. Sorry if the numbers don't show too nice above...
Evans

I can understand your anger. There are problems like this that can sometimes drive us nuts !

Many of us have been through this type of situations.

Numeric comparison can be a pain, i hve faced big problems in my software with it.

The only reliable way i have found to test and make sure numbers are equal is :

IF ABS(VALUE1 -VALUE2) < 0.009

Looks stupid but it has worked for me.

HTH

:D There is always a solution !

Richard
http://www.cbati.com

Uestudio
Fwh 13.05 Harbour 3.2 MSVC 2013
User avatar
Richard Chidiak
Posts: 946
Joined: Thu Oct 06, 2005 7:05 pm
Location: France
Contact:

Re: Numeric comparisons

Post by Richard Chidiak »

E. Bartzokas wrote:Hi all,
Either I got crazy, or something else is happening...
I have a problem with the 32-bit that does not exist in the 16-bit, or DOS.

To better describe the problem:

1. I have a database with four CHAR fields (width 20) that hold some numbers (amounts) with four decimals in them.

Example:
Soc.Security Medicare Withholding Total Amount
1172.0200 275.2700 839.0600 2291.3500

If I get the VAL() of each database field from the above, round them to 2 decimals, then add them up, I get the result 2291.35 (CORRECT) !!!

Now, the second record in the database contains these:
Soc.Security Medicare Withholding Total Amount
1019.5000 238.4400 679.9000 1937.8400

In my loops, I need to compare if the three first values of the fields, are equal to the Total Amount.

As I state above, the first example record results to .T. (equal).
The second record, and many more records (practically all of them are equal, if I add them up they match the total amount value, which notice that it is also of CHAR type in the field, converted to VAL(), and Rounded to 2 decimals, I get the same incorrect result (.F.), when I do the comparison.

Since I made the thought that either I'm too stressed from working too much, or getting too old, I wouldn't like to mention about having problems with FWH numeric comparisons.... thus, I copied the code from the 32-bit PRG and pasted it into a stand-alone PRG which I compiled in FW 16-bit, and another one in MS-DOS.

Both the 16-bit applications came up with .T. everywhere where they should be .T. of course. To make things easier, all the fields match the Total amount in the same record.

Now I am sitting down and do nothing further because this issue has driven me crazy. I have more than 30 years in the field, and am sure that there is nothing wrong with my code... simple things, that in addition, are working perfectly in the 16-bit environment.

Can some of my friends try to reproduce and verify that the above numbers, if read from a dbf stored as characters, do not match the total amount?

I would be grateful if I receive some answer(s).

Kind regards
Evans
ps. Sorry if the numbers don't show too nice above...
Evans

without rounding, if you add your first 3 values the result is 2286.35 for the first record, second is ok

Here is a piece of code that shows that record 1 is not ok but record 2 is OK

I only test on fwh xharbour 32 bits

#INCLUDE "FIVEWIN.CH"

REQUEST DBFCDX

FUNCTION MAIN()

LOCAL aadbf := {}

RDDSETDEFAULT("DBFCDX")

ERASE "EVANS.DBF"
aADBF := {}
AADD(aADBF, {"F1", "N", 10, 4 })
AADD(aADBF, {"F2", "N", 10, 4 })
AADD(aADBF, {"F3", "N", 10, 4 })
AADD(aADBF, {"F4", "N", 10, 2 })
DBCREATE("EVANS", aADBF)

USE EVANS NEW
APPEND BLANK
REPLACE F1 WITH 1172.0200
REPLACE F2 WITH 275.2700
REPLACE F3 WITH 839.0600
REPLACE F4 WITH 2291.3500

APPEND BLANK
REPLACE F1 WITH 1019.5000
REPLACE F2 WITH 238.4400
REPLACE F3 WITH 679.9000
REPLACE F4 WITH 1937.8400

DBGOTOP()

DTOT := F1 + F2 + F3
IF ABS(DTOT - F4) < 0.009
MSGINFO("FIRST IS OK")
ELSE
MSGINFO("FIRST IS not ok")
ENDIF

DBSKIP()

DTOT := F1 + F2 + F3
IF ABS(DTOT - F4) < 0.009
MSGINFO("SECOND IS OK")
ELSE
MSGINFO("SECOND IS not ok")
ENDIF

EVANS->(DBCLOSEAREA())

RETURN NIL
http://www.cbati.com

Uestudio
Fwh 13.05 Harbour 3.2 MSVC 2013
User avatar
Enrico Maria Giordano
Posts: 7355
Joined: Thu Oct 06, 2005 8:17 pm
Location: Roma - Italia
Contact:

Re: Numeric comparisons

Post by Enrico Maria Giordano »

E. Bartzokas wrote:Hi all,
Either I got crazy, or something else is happening...
I have a problem with the 32-bit that does not exist in the 16-bit, or DOS.
It is a very well known problem with floating point numbers and it doesn't depend on platform or language used. The simple solution is: round before compare.

EMG
User avatar
E. Bartzokas
Posts: 114
Joined: Tue Feb 14, 2006 8:13 am
Location: Corinth, Greece

Re: Numeric comparisons

Post by E. Bartzokas »

Richard Chidiak wrote:
Evans

I can understand your anger. There are problems like this that can sometimes drive us nuts !

Many of us have been through this type of situations.

Numeric comparison can be a pain, i hve faced big problems in my software with it.

The only reliable way i have found to test and make sure numbers are equal is :

IF ABS(VALUE1 -VALUE2) < 0.009

Looks stupid but it has worked for me.

HTH

:D There is always a solution !

Richard
Richard,
Thanks again...
It still does not work...
No matter what I have tried...
ABS() doesn't work either.

Thanks though...
Kind regards
Evans
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Post by Antonio Linares »

Evans,

Don't use decimals numbers for the comparison. This sample works fine:

Code: Select all

function Main()

   MsgInfo( ( 1019.5000 + 238.4400 + 679.9000 ) * 10000 == 1937.8400 * 10000 )
   
return nil   
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
James Bott
Posts: 4654
Joined: Fri Nov 18, 2005 4:52 pm
Location: San Diego, California, USA
Contact:

Post by James Bott »

Evans,

As Enrico says, it is a constant problem with floating point numbers.

However, the below code seems to work. The trick is to convert the sum to string then back to numeric. Give it a try on more numbers.

Tested with FWH Aug 2006 build and xHarbour.

James

Code: Select all

#include "fivewin.ch"

function main()
   local ss, med, with, total

   ss:= val("1019.5000")
   med:=val("238.4400")
   with:=val("679.9000")
   total:= val("1937.8400")

   msgInfo( val(str(ss+med+with)) = total )

return nil
User avatar
E. Bartzokas
Posts: 114
Joined: Tue Feb 14, 2006 8:13 am
Location: Corinth, Greece

Post by E. Bartzokas »

James Bott wrote:Evans,

As Enrico says, it is a constant problem with floating point numbers.

However, the below code seems to work. The trick is to convert the sum to string then back to numeric. Give it a try on more numbers.

Tested with FWH Aug 2006 build and xHarbour.

James

Code: Select all

#include "fivewin.ch"

function main()
   local ss, med, with, total

   ss:= val("1019.5000")
   med:=val("238.4400")
   with:=val("679.9000")
   total:= val("1937.8400")

   msgInfo( val(str(ss+med+with)) = total )

return nil
You guys are all terific... Thanks...
I'm sure that one of the suggested solutions will work (somehow).
I'll do the code changes in the morning, and will post my code.

Thanks to all of you.
You are wonderful....

Evans

ps. Any possibility to have a "real" floating point library solution ?
R.F.
Posts: 840
Joined: Thu Oct 13, 2005 7:05 pm

Post by R.F. »

Turn numeric to string, then compare

x:= 199.50
y:= 199.50

IF x = y // this will fail !!!!!

IF STR(x,2) = STR(y,2) // this will work....

and unfortunatly no, there's no solution for such problem, no in xHabour, nor in Clipper, nor in Visual Bullshit, sorry Basic, nor in Delphi, or in Java, all the languages handling floating point routines have the very same behave.
Saludos
R.F.
User avatar
E. Bartzokas
Posts: 114
Joined: Tue Feb 14, 2006 8:13 am
Location: Corinth, Greece

Post by E. Bartzokas »

RF wrote:Turn numeric to string, then compare

x:= 199.50
y:= 199.50

IF x = y // this will fail !!!!!

IF STR(x,2) = STR(y,2) // this will work....

and unfortunatly no, there's no solution for such problem, no in xHabour, nor in Clipper, nor in Visual Bullshit, sorry Basic, nor in Delphi, or in Java, all the languages handling floating point routines have the very same behave.
You guys are all great!
I couldn't be getting any more help than this provided to me with this posting.

I solved the problem by comparing the resulted numerics, by converting them to strings such as Str( 1.30 + 2.30 + 3.30, 15,2) == Str(6.90,15,2)

And I was thinking about going back to elementary school
:shock:

Thanks to all for one more time

Kind regards from Corinth, Greece
Evans
Post Reply