Kbase P88093: Can subtraction of two decimal numbers having the same decimals precision have rounding problems?
Autor |
  Progress Software Corporation - Progress |
Acesso |
  Público |
Publicação |
  16/07/2004 |
|
Status: Unverified
GOAL:
Can subtraction of two decimal numbers having the same decimals precision have rounding problems?
GOAL:
If x, y are two decimal variables specified with a decimals 4 precision, can their difference, d = x - y; which is also a decimal variable specified to the same decimals 4 precision; ever suffer a loss of data due to ROUNDING?
FIX:
No, the Progress 4GL subtraction operation in does not have any rounding problems.
The following code empirically proves this by looping a million times, generating two random decimals in each iteration and confirming that their difference does not suffer any loss of data due to rounding:
DEFINE VARIABLE dx AS DECIMAL NO-UNDO DECIMALS 4 FORMAT "(9.9999)".
DEFINE VARIABLE dy AS DECIMAL NO-UNDO DECIMALS 4 FORMAT "(9.9999)".
DEFINE VARIABLE ix AS INTEGER NO-UNDO FORMAT "(99999)".
DEFINE VARIABLE iy AS INTEGER NO-UNDO FORMAT "(99999)".
DEFINE VARIABLE iIntegerDifference AS INTEGER NO-UNDO FORMAT "(99999)".
DEFINE VARIABLE dDecimalDifference AS DECIMAL NO-UNDO DECIMALS 4 FORMAT "(9.9999)".
DEFINE VARIABLE iCounter AS INTEGER NO-UNDO.
/* functions to generate random integers and cook decimals from these integers */
FUNCTION udfGeneratedRandomInteger RETURNS INTEGER FORWARD.
FUNCTION udfGeneratedDecimalFromInteger RETURNS DECIMAL (INPUT piVariable1 AS INTEGER) FORWARD.
/* functions to generate integer difference and decimal difference of the generated numbers*/
FUNCTION udfSubtractTheIntegers RETURNS INTEGER (INPUT piVariable1 AS INTEGER, INPUT piVariable2 AS INTEGER) FORWARD.
FUNCTION udfSubtractTheDecimals RETURNS DECIMAL (INPUT piVariable1 AS DECIMAL, INPUT piVariable2 AS DECIMAL) FORWARD.
/* loop a million times */
REPEAT iCounter = 1 TO 1000000:
ASSIGN
ix = udfGeneratedRandomInteger()
iy = udfGeneratedRandomInteger()
dx = udfGeneratedDecimalFromInteger(ix)
dy = udfGeneratedDecimalFromInteger(iy)
iIntegerDifference = udfSubtractTheIntegers(ix, iy)
dDecimalDifference = udfSubtractTheDecimals(dx, dy).
/*** If decimal difference is ROUNDED, then message the strings involved ***/
IF STRING(iIntegerDifference, "99999") <>
REPLACE(STRING(dDecimalDifference, "9.9999"),'.','') THEN
MESSAGE ix dx iy dy STRING(iIntegerDifference, "99999") REPLACE(STRING(dDecimalDifference, "9.9999"),'.','')
VIEW-AS ALERT-BOX INFO BUTTONS OK.
END.
/* Generate a random integer */
FUNCTION udfGeneratedRandomInteger RETURNS INTEGER:
RETURN RANDOM(10000,99999).
END.
/* Cook a decimal from the generated integer */
FUNCTION udfGeneratedDecimalFromInteger RETURNS DECIMAL (INPUT piVariable AS INTEGER):
DEFINE VARIABLE c AS CHARACTER NO-UNDO.
c = STRING(piVariable).
SUBSTRING(c,1,1) = SUBSTRING(c,1,1) + '.'.
RETURN DECIMAL(c).
END.
/* Get the integer difference */
FUNCTION udfSubtractTheIntegers RETURNS INTEGER (INPUT piVariable1 AS INTEGER, INPUT piVariable2 AS INTEGER):
RETURN ABS(piVariable1 - piVariable2).
END.
/* Get the decimal difference */
FUNCTION udfSubtractTheDecimals RETURNS DECIMAL (INPUT piVariable1 AS DECIMAL, INPUT piVariable2 AS DECIMAL):
RETURN ABS(piVariable1 - piVariable2).
END.