Rounding Numbers: Difference between revisions

From DataFlex Wiki
Jump to navigationJump to search
Line 58: Line 58:


[[Image:ROUNDNUM.zip| Download Roundnum.fnc (zipfile)]]
[[Image:ROUNDNUM.zip| Download Roundnum.fnc (zipfile)]]
hold on ... there's an upload restriction preventing this...
hold on ... there's an upload restriction preventing this... will upload it later...


____
=== Source ===
// ===========================================================================
// ===========================================================================
//
//
// The ROUND_NUMBER global function has been designed to return the rounded
// The ROUND_NUMBER global function has been designed to return the rounded
// value of a given 'numeric' argument at a specified rounding precision.
// value of a given 'numeric' argument at a specified rounding precision.
//
//
// The function requires two arguments, as follows:-
// The function requires two arguments, as follows:-
//
//
// (a) The numeric value to be rounded, where the range of valid values is
// (a) The numeric value to be rounded, where the range of valid values is
//    +/- 99,999,999,999,999.99999999.
//    +/- 99,999,999,999,999.99999999.
//
//
// (b) The rounding precision required.  This must be an integer value in the
// (b) The rounding precision required.  This must be an integer value in the
//    range -13 to +8.  If a value outside this range is used, the nearest
//    range -13 to +8.  If a value outside this range is used, the nearest
//    threshold value is substituted.
//    threshold value is substituted.
//
//
//    Values in the range +1 to +7 perform rounding on the decimal part of
//    Values in the range +1 to +7 perform rounding on the decimal part of
//    the number.  A value of +8 will perform no rounding at all.  A zero
//    the number.  A value of +8 will perform no rounding at all.  A zero
//    value will round to the nearest whole number.  Values -1 to -13 will
//    value will round to the nearest whole number.  Values -1 to -13 will
//    round progressively to the left of the decimal point (a frequent
//    round progressively to the left of the decimal point (a frequent
//    requirement in financial reporting).
//    requirement in financial reporting).
//
//
// If the result of the rounding produces a value outside the valid numeric
// If the result of the rounding produces a value outside the valid numeric
// range (+/- 99,999,999,999,999.99999999) then a zero value is returned.
// range (+/- 99,999,999,999,999.99999999) then a zero value is returned.
//
//
// Assumptions:-  The only assumptions made have been that the range of
// Assumptions:-  The only assumptions made have been that the range of
// numeric values and the limit of eight decimal places are unlikely to change
// numeric values and the limit of eight decimal places are unlikely to change
// in the forseeable future.
// in the forseeable future.
//
//
// Examples:-
// Examples:-
//
//
//  1st Argument      2nd Argument  Return Value
//  1st Argument      2nd Argument  Return Value
//  ------------      ------------  ------------
//  ------------      ------------  ------------
//  123456.87654321        8        123456.87654321
//  123456.87654321        8        123456.87654321
//  123456.87654321        2        123456.88
//  123456.87654321        2        123456.88
// -123456.87654321        2        -123456.88
// -123456.87654321        2        -123456.88
//  123456.98765432        0        123457
//  123456.98765432        0        123457
// -123456.98765432        -1        -123460
// -123456.98765432        -1        -123460
//  123456.98765432        -2        123500
//  123456.98765432        -2        123500
//  123456.98765432        -3        123000
//  123456.98765432        -3        123000
//  987654                -4        990000
//  987654                -4        990000
//  987654                -5        1000000
//  987654                -5        1000000
//  987654                -6        1000000
//  987654                -6        1000000
//  987654                -7              0
//  987654                -7              0
//
//
// ===========================================================================
// ===========================================================================


Line 153: Line 110:




Function Round_Number GLOBAL number nVal integer iRnd returns Number
  Function Round_Number GLOBAL number nVal integer iRnd returns Number
 
 
 
  // If the rounding precision falls in the range -5 to +8, then return:-
 
 
 
  If (iRnd >= -5) Function_Return ;


    // If the rounding precision falls in the range -5 to +8, then return:-
    If (iRnd >= -5) Function_Return ;
     (Number(Abs(nVal) / nVal) * 0.5 / (Number(10 ^ (iRnd min 8))) + nVal ;
     (Number(Abs(nVal) / nVal) * 0.5 / (Number(10 ^ (iRnd min 8))) + nVal ;
       / (Number(10 ^ (8 - (iRnd min 8)))) * (Number(10 ^ (8 - (iRnd min 8)))))
       / (Number(10 ^ (8 - (iRnd min 8)))) * (Number(10 ^ (8 - (iRnd min 8)))))
   // Else, where the rounding precision is in the range -6 to -13, return:-
   // Else, where the rounding precision is in the range -6 to -13, return:-
   Function_Return ;
   Function_Return ;
     (Number(Abs(nVal) / nVal) * 0.5 * (Number(10 ^ (Abs(iRnd) min 13))) ;
     (Number(Abs(nVal) / nVal) * 0.5 * (Number(10 ^ (Abs(iRnd) min 13))) ;
       + nVal / (Number(10 ^ 13)) / (Number(10 ^ ((Abs(iRnd) - 5) min 8))) ;
       + nVal / (Number(10 ^ 13)) / (Number(10 ^ ((Abs(iRnd) - 5) min 8))) ;
         * (Number(10 ^ 13)) * (Number(10 ^ ((Abs(iRnd) - 5) min 8))))
         * (Number(10 ^ 13)) * (Number(10 ^ ((Abs(iRnd) - 5) min 8))))
 
  End_Function
 
 
End_Function

Revision as of 15:07, 28 September 2007

Rounding Numbers

The following has been taken from the DAW newsgroup, User Contributed Oct 6 2000

MARF - A Mutually Agreed Rounding Function?!

Aside from UI issues, OS and hardware problems, perhaps one of the most frequently recurring themes in both the old DAC CompuServe Forum, and now here, has been 'How to perform proper rounding of numeric values'.

Interestingly, each time the topic reappears as a new thread, nobody ever refers the questioner back to the previous threads on the subject. It is always a great opportunity to air one's own (usually strictly limited) solution to the problem!

Well, I propose that we use this message thread to, if possible, finally agree upon a proper specification and solution to this problem ... the one that DAC forgot to supply us ... and finally lay this ghost to rest!

So let me kick-off.

Here is what I expect of a proper Rounding function:-

(a) It should be able to cope with all numbers in the DataFlex numeric range ie. ± 99,999,999,999,999.99999999.

(b) Rounding should occur when the digit to the right of the rounding position is 5 or above. I take this to be a reasonably 'international' convention.

(c) It should be possible to round to any degree of precision. In other words, it should be capable of rounding to any position to the left of the decimal delimiter as well as to the right of it. This, after all, is a frequent requirement in financial reporting. So, for example, if I wish to round to the nearest thousand, then a value of 72637.54 should be returned as 73000.


I have attached a file named ROUNDNUM.FNC which contains a global function that attempts to meet these requirements. Use of the function, named ROUND_NUMBER, is fully documented therein.

My approach is substantially based on some code originally presented by Hendrick van Niekerk in a CompuServe message in October 1997. I note that he has repeated the code in a message reply in the VDF NG on 11-Jun-2000.

I prefer Hendrick's method to all the others I have yet seen. His code is actually contained in a macro command named ROUND THEN. Basically all I have done is to convert his macro into a global function and then extended the scope of the code to provide for rounding to a more flexible degree of precision.

So ... well ... thanks Hendrick!

Regards,

Michael Pilsworth

Download Roundnum.fnc (zipfile) hold on ... there's an upload restriction preventing this... will upload it later...

Source

// =========================================================================== // // The ROUND_NUMBER global function has been designed to return the rounded // value of a given 'numeric' argument at a specified rounding precision. // // The function requires two arguments, as follows:- // // (a) The numeric value to be rounded, where the range of valid values is // +/- 99,999,999,999,999.99999999. // // (b) The rounding precision required. This must be an integer value in the // range -13 to +8. If a value outside this range is used, the nearest // threshold value is substituted. // // Values in the range +1 to +7 perform rounding on the decimal part of // the number. A value of +8 will perform no rounding at all. A zero // value will round to the nearest whole number. Values -1 to -13 will // round progressively to the left of the decimal point (a frequent // requirement in financial reporting). // // If the result of the rounding produces a value outside the valid numeric // range (+/- 99,999,999,999,999.99999999) then a zero value is returned. // // Assumptions:- The only assumptions made have been that the range of // numeric values and the limit of eight decimal places are unlikely to change // in the forseeable future. // // Examples:- // // 1st Argument 2nd Argument Return Value // ------------ ------------ ------------ // 123456.87654321 8 123456.87654321 // 123456.87654321 2 123456.88 // -123456.87654321 2 -123456.88 // 123456.98765432 0 123457 // -123456.98765432 -1 -123460 // 123456.98765432 -2 123500 // 123456.98765432 -3 123000 // 987654 -4 990000 // 987654 -5 1000000 // 987654 -6 1000000 // 987654 -7 0 // // ===========================================================================



 Function Round_Number GLOBAL number nVal integer iRnd returns Number
   // If the rounding precision falls in the range -5 to +8, then return:-
   If (iRnd >= -5) Function_Return ;
   (Number(Abs(nVal) / nVal) * 0.5 / (Number(10 ^ (iRnd min 8))) + nVal ;
     / (Number(10 ^ (8 - (iRnd min 8)))) * (Number(10 ^ (8 - (iRnd min 8)))))
 // Else, where the rounding precision is in the range -6 to -13, return:-
 Function_Return ;
   (Number(Abs(nVal) / nVal) * 0.5 * (Number(10 ^ (Abs(iRnd) min 13))) ;
     + nVal / (Number(10 ^ 13)) / (Number(10 ^ ((Abs(iRnd) - 5) min 8))) ;
       * (Number(10 ^ 13)) * (Number(10 ^ ((Abs(iRnd) - 5) min 8))))
 End_Function