Author Topic: FIX issue  (Read 6455 times)

0 Members and 1 Guest are viewing this topic.

domenicomaria

  • Swamp Rat
  • Posts: 723
FIX issue
« on: April 22, 2021, 10:53:09 AM »
(setq x-deg                  12.3456                    )    ; 12.3456
(setq i-deg                   (fix x-deg)                 )   ; 12      
(setq sub-deg               (- x-deg i-deg)           )   ; 0.3456   
(setq sub-deg-10000     (* sub-deg 10000.0)  )   ; 3456.0   
(setq i-sub-deg-10000   (fix sub-deg-10000 )  )   ; 3455 ? ? ?

why ?

danAllen

  • Newt
  • Posts: 132
Re: FIX issue
« Reply #1 on: April 22, 2021, 11:14:13 AM »
On Bricscad v15 I get this:
Code: [Select]
: (setq x-deg 12.3456 )
12.3456
: (setq i-deg (fix x-deg) )
12
: (setq sub-deg (- x-deg i-deg) )
0.345599999999999
: (setq sub-deg-10000 (* sub-deg 10000.0) )
3455.99999999999
: (setq i-sub-deg-10000 (fix sub-deg-10000 ) )
3455

my LUPREC is set to 8, could yours be set to smaller hiding the .99999?

domenicomaria

  • Swamp Rat
  • Posts: 723
Re: FIX issue
« Reply #2 on: April 22, 2021, 11:26:19 AM »
my LUPREC is set to 8, too !

But I get what I wrote in my first post !

And I don't understand why.

I get    sub-deg-10000 = 3456.0

but (FIX sub-deg-10000) = 3455 ! ! !  

ribarm

  • Gator
  • Posts: 3225
  • Marko Ribar, architect
Re: FIX issue
« Reply #3 on: April 22, 2021, 11:59:23 AM »
last line :

try (it won't influence on integer result, but it will fix an issue) :

(setq i-sub-deg-10000   (fix (+ sub-deg-10000 0.01))  )
Marko Ribar, d.i.a. (graduated engineer of architecture)

:)

M.R. on Youtube

CincyJeff

  • Newt
  • Posts: 89
Re: FIX issue
« Reply #4 on: April 22, 2021, 12:58:13 PM »
(rtos (* sub-deg 10000.0) 2 10) -> "3456.0000000000"
(rtos (* sub-deg 10000.0) 2 11) -> "3455.99999999999"
You could (fix (atof (rtos...

domenicomaria

  • Swamp Rat
  • Posts: 723
Re: FIX issue
« Reply #5 on: April 22, 2021, 01:41:00 PM »
last line :

try (it won't influence on integer result, but it will fix an issue) :

(setq i-sub-deg-10000   (fix (+ sub-deg-10000 0.01))  )

There are some workarounds, but, why this happens ?

Is it a BUG ?

danAllen

  • Newt
  • Posts: 132
Re: FIX issue
« Reply #6 on: April 22, 2021, 02:18:38 PM »
why use FIX instead of a rounding function?

Code: [Select]
;;;==========================================================
;;;Rounding function - Joe Burke - 2/23/03
;;;==========================================================
(defun SAA_round (value to)
   (if (zerop to) value
     (* (atoi (rtos (/ (float value) to) 2 0)) to))
)

: (saa_round 3455.99999999999 1)
3456

see https://www.theswamp.org/index.php?topic=44487.0

domenicomaria

  • Swamp Rat
  • Posts: 723
Re: FIX issue
« Reply #7 on: April 22, 2021, 02:54:17 PM »
Quote
(saa_round 3455.99999999999 1) -> 3456

the problem is NOT to ROUND a number.

The problem is WHY this happens ?


I have a simple math problem.

And I want to solve it with math.

And I don't want to use strings.

Not possible in VLisp?


domenicomaria

  • Swamp Rat
  • Posts: 723
Re: FIX issue
« Reply #8 on: April 22, 2021, 02:59:44 PM »
Code - Auto/Visual Lisp: [Select]
  1. (defun :GGMMSS>RAD (x-ggmmss / x-gg x-ggmmss-lst x-ggmmss-s x-mm x-mmss x-ss)
  2.         (setvar "dimzin" 0)
  3.         (setq   x-ggmmss-s      (rtos x-ggmmss 2 4)
  4.                 x-ggmmss-lst    (LM:str->lst x-ggmmss-s ".")
  5.                 x-gg            (read (nth 0 x-ggmmss-lst) )
  6.                 x-mmss          (nth 1 x-ggmmss-lst)
  7.                 x-mm            (read (substr x-mmss 1 2) )
  8.                 x-ss            (read (substr x-mmss 3 2) )                            
  9.         )
  10.         (/ (*   (+ x-gg (/ x-mm 60.0) (/  x-ss 3600.0) ) pi) 180.0)
  11. )
  12.  

I need to convert degrees in sexagesimal format to radians.
And this function works well.

But I used strings.

Is there a mathematical-only solution in VLISP?
« Last Edit: April 22, 2021, 05:17:02 PM by domenicomaria »

domenicomaria

  • Swamp Rat
  • Posts: 723
Re: FIX issue
« Reply #9 on: April 22, 2021, 05:12:08 PM »
anyway this works :

Code - Auto/Visual Lisp: [Select]
  1. (setq   ggmmss          123.4567
  2.         gg              (float (fix ggmmss) )
  3.         mmss            (- ggmmss gg)
  4.         mmss-100        (* mmss 100.0)
  5.         mm              (float (fix mmss-100) )
  6.         ss              (- mmss-100 mm)
  7.         ss              (* ss 100.0)
  8. )
  9. (list gg mm ss)
« Last Edit: April 22, 2021, 05:16:11 PM by domenicomaria »

Lee Mac

  • Seagull
  • Posts: 12906
  • London, England
Re: FIX issue
« Reply #10 on: April 22, 2021, 05:41:18 PM »
It is worth noting that issues such as this are not specific to AutoLISP or indeed any programming language, but rather apply to computing in general.

This issue arises because a computer has finite memory in which data may be stored, and consequently not all numbers can be represented exactly, but instead must be approximated and stored in an agreed format (specifically, in this case, the double-precision floating-point format, or simply 'double') which has inherent compromises at the extent of its precision in order to be useful under a wide range of applications (i.e. affording an ability to represent both very large numbers (to an order of magnitude of 1e308) with low precision, and very small numbers with high precision).

Just as one third cannot be represented exactly in base 10 [decimal] (instead yielding the infinitely recurring decimal 0.333...10) but can be represented exactly in base 3 (as 0.13), there are many numbers which equally cannot be represented exactly in base 2 [binary], and indeed, the same would arise for any chosen base.

As a result of this hard limit on the level of precision to which any number may be stored, arithmetic errors begin to creep into calculations where rounding occurs at the very limit of precision for almost every calculation, and such infinitesimal errors propagate with repeated & compound calculations.

In your particular example, we see that performing the subtraction of the integer from the double, followed by a multiplication by the double 10000.0 introduces an infinitesimal rounding error at the limit of precision of the double, which may be observed by converting the double to a string using the rtos function:

Code - Auto/Visual Lisp: [Select]
  1. _$ (rtos sub-deg-10000 2 20)
  2. "3455.999999999992"

Now, since the fix function merely removes the fractional component of the data to yield an integer value, the introduction of this rounding error will cause the function to return 3455 instead of 3456.

As such, when working with doubles, we must always account for the possibility of rounding and always include a 'fuzz factor' or tolerance when performing any operation which will either attempt to yield an exact value (such as the use of the fix function), or compare a double with an exact value (such as you might with the = operator when comparing two integers).

In this case, I would suggest the following (you may decide to opt for a smaller tolerance, such as 1e-12):
Code - Auto/Visual Lisp: [Select]
  1. _$ (fix (+ sub-deg-10000 1e-8))
  2. 3456

Or, where a comparison is concerned, the use of the equal function with an appropriate tolerance:
Code - Auto/Visual Lisp: [Select]
  1. _$ (equal 3456 sub-deg-10000 1e-8)
  2. T
« Last Edit: April 22, 2021, 05:48:30 PM by Lee Mac »

danAllen

  • Newt
  • Posts: 132
Re: FIX issue
« Reply #11 on: April 22, 2021, 11:53:48 PM »
Also I believe AutoLisp only holds 16 digits of significance for real numbers. This can be shown by progressively adding a tens digit to the pi. (ten power?)
Code: [Select]
: (setq i 1)
1
: (repeat 16 (princ (strcat "\n" (rtos (+ (setq i (* i 10)) pi) 2 32))))

13.14159265358979
103.1415926535898
1003.141592653590
10003.14159265359
100003.1415926536
1000003.141592654
10000003.14159265
100000003.1415927
1000000003.141593
10000000003.14159
100000000003.1416
1000000000003.142
10000000000003.14
100000000000003.1
1000000000000003
1.000000000000000

Even though RTOS is being asked to show 32 digits of significance, it only shows 16.

Further by adding increasing 10, 100, 1000 etc to pi, then subtracting, significant decimal numbers are lost

Code: [Select]
: (setq i 1)
1
: (repeat 16 (princ (strcat "\n" (rtos (- (+ (setq i (* i 10)) pi) i) 2 32))))

3.141592653589793
3.141592653589797
3.141592653589782
3.141592653590124
3.141592653584667
3.141592653584667
3.141592653468251
3.141592651605606
3.141592621803284
3.141592025756836
3.141586303710938
3.141601562500000
3.140625000000000
3.140625000000000
3.125000000000000
4.000000000000000

(I'm probably missing something mathematically, but just wanted to make the point that CAD has a limit to precision)

domenicomaria

  • Swamp Rat
  • Posts: 723
Re: FIX issue
« Reply #12 on: April 23, 2021, 05:44:10 AM »
Quote
This issue arises because a computer has finite memory in which data may be stored, and consequently not all numbers can be represented exactly, but instead must be approximated and stored in an agreed format (specifically, in this case, the double-precision floating-point format, or simply 'double') which has inherent compromises at the extent of its precision in order to be useful under a wide range of applications (i.e. affording an ability to represent both very large numbers (to an order of magnitude of 1e308) with low precision, and very small numbers with high precision).

I know this problem, well.

And for that I think someone should implement another version
of the FIX command with limitations.

But within these limits, the command should work well.

The limitations could be the size of the number and the number of digits.

it is not elegant and acceptable that
to get the integer part of a number,
one must first convert it to a string,
and then divide it and take the part before the point
and then use the READ command . . .

. . . it is not acceptable !


Marc'Antonio Alessi

  • Swamp Rat
  • Posts: 1451
  • Marco
Re: FIX issue
« Reply #13 on: April 23, 2021, 10:29:40 AM »

I need to convert degrees in sexagesimal format to radians.
Is there a mathematical-only solution in VLISP?
Sexagesimal format is : 123°34'56"   :-o

danAllen

  • Newt
  • Posts: 132
Re: FIX issue
« Reply #14 on: April 23, 2021, 10:56:08 AM »
Rereading the first post, I see the real question is why does just subtracting an integer result in repeating decimal?
Code: [Select]
: (- 12.3456 12)
0.345599999999999
: (- 12.3456 12.0)
0.345599999999999
: (- 12.3 12)
0.300000000000001