round function

21 views
Skip to first unread message

Juan Ayala Cervantes

unread,
Apr 25, 2020, 10:40:06 PM4/25/20
to CLIPSESG

Hello:

working with the ROUND function I can see that it does not round well for example 5.5 (it does 5 and not 6) and any number ending in .5.

CLIPS (6.31 6/12/19)

 

CLIPS> (round 5.5)

5

CLIPS> (round 5.51)

6

CLIPS> (round 5.49)

5

CLIPS>

 

To try to save this I made a function but when I perform it I see this:

I don't understand where the error is?

if I repeat the same function but changing the numbers, if it works for me.

        CLIPS (6.31 6/12/19)

CLIPS> (deffunction redondeo

                (?numero)

                (if (and(>=(- ?numero (integer ?numero)) 0)

 (<= (- ?numero (integer ?numero)) 0.04))then (printout t (integer ?numero))))

CLIPS> (redondeo 5.04)

FALSE

CLIPS> (redondeo 3.04)

FALSE

CLIPS> (redondeo 3.03)

3

 

CLIPS> (deffunction redondeo

                (?numero)

                (if (and(>=(- ?numero (integer ?numero)) 0.05)

 (<= (- ?numero (integer ?numero)) 0.14))then (printout t (integer ?numero))))

CLIPS> (redondeo 0.14)

0

CLIPS> (redondeo 6.14)

6

 

Denis Berthier

unread,
Apr 26, 2020, 1:21:24 AM4/26/20
to CLIPSESG
Deciding that 5.5 should be rounded to 5 or to 6 is somewhat arbitrary.

(round 5.500001) -> 6

(round 5.499999) -> 5

For me, the round function works.

Juan Ayala Cervantes

unread,
Apr 26, 2020, 4:40:02 AM4/26/20
to CLIPSESG
You are right it is something arbitrary, like many things in this world.
But it is not exact.
Thanks for the idea I will add 0.0000000001 to each number, that way I will have more accuracy when doing the calculations.


On Sunday, April 26, 2020 at 4:40:06 AM UTC+2, Juan Ayala Cervantes wrote:

CLIPS Support

unread,
Apr 26, 2020, 9:56:20 PM4/26/20
to CLIPSESG
The behavior for the round function is in the CLIPS Basic Programming Guide:

The round function rounds its only argument (which should be a numeric expression) toward the closest integer. If the argument is exactly between two integers, it is rounded down. 

It does make more sense to use the same behavior as the C library routine that rounds away from zero if the argument is exactly between two integers. The code for that function was written almost 30 years ago, so that option probably was not available when the code was originally written.

If you can recompile the CLIPS source code, you can modify the RoundFunction in emathfun.c changing this line:

     { return((long long) ceil(ValueToDouble(result.value) - 0.5)); }

to this

     { return((long long) round(ValueToDouble(result.value))); }

Alternatively, you can define a method that overrides the built-in round function:

CLIPS> (round 5.5)
5
CLIPS> (round 5.51)
6
CLIPS> (round -5.5)
-6
CLIPS> (round -5.51)
-6
CLIPS> 
(defmethod round ((?num FLOAT))
   (bind ?negate (< ?num 0))
   (bind ?num (abs ?num))
   (bind ?inum (integer ?num))
   (bind ?frac (- ?num ?inum))
   (if (>= ?frac 0.5)
      then (bind ?inum (+ ?inum 1)))
   (if ?negate
      then (- 0 ?inum)
      else ?inum))
CLIPS> (round 5.5)
6
CLIPS> (round 5.51)
6
CLIPS> (round -5.5)
-6
CLIPS> (round -5.51)
-6
CLIPS> 
Reply all
Reply to author
Forward
0 new messages