May 01, 2024, 01:26:33 AM

News:

Own IWBasic 2.x ? -----> Get your free upgrade to 3.x now.........


Does anyone know how to get around rounding problems?

Started by Egil, October 25, 2014, 11:30:06 AM

Previous topic - Next topic

0 Members and 1 Guest are viewing this topic.

Egil

Clint,

Compiled your example just know. Works like a dream, and fast.
Think I'll have to find the documentation of that library, and download it. Mybe there are other functions in there that my be of use for my plans...

When I started this work, I just thought of using it for satellites with low earth orbist, but with this resolution i really beleive I'm set for outer space... ;D
Support Amateur Radio  -  Have a ham  for dinner!

Egil

Support Amateur Radio  -  Have a ham  for dinner!

ckoehn

Hope things go well for you Egil, good luck.

Later,
Clint

ckoehn

I did the declares by copying an include from PowerBASIC forum and looking through this header file.

If you need help with some paticular function let me know.

Later,
Clint

Logman

October 31, 2014, 10:11:33 AM #29 Last Edit: October 31, 2014, 02:59:18 PM by Logman
Just to weigh in with my two cents. Here is a piece of code that provides 16 digits worth of precision.

Remember, when using the DOUBLE floating point format (QWORD in assembly), the best precision you can get is 16 digits. If your processor is capable of 128-bit SSE or 256-bit AVX computations in either the XMM or YMM registers, then you can get precision that is greater then the number of stars in the known universe. That's a big number.

You can write your own software routines to get the precision you want, but that would be time-consuming. However, IWBasic has lot's of capabilities and one is that you can include inline assembly statements in your code to get some of the precision you desire. Here's an example:



[font=consolas]REM ----------------------------------------------------------------------
REM Program to convert degrees to radians and radians to degrees
REM Using the FPU allows calculations to be performed to 20 digits
REM of accuracy before being saved as double precision floating
REM values that are limited to 16 digits of accuracy.
REM
REM NOTE: Double precision floating point values are 64-bits wide
REM       and only have an accuracy of 16 digits. Therefore,
REM       trying to get more accuracy is futile when operating in
REM       32-bit protected mode using the flat memory model. We
REM       could employ the 126-bit or 256-bit XMM/YMM registers,
REM       but the processor would have to be capable of SEE/AVX
REM       operations and the programmer would have to use software
REM       algorithms as SSE/AVX have no hardware support for
REM       scalar floating point operations larger than QWORD.
REM
REM Degrees = radians x pi/180
REM Radians = degrees x 180/pi
REM -------------------------------------------------------------------------
DECLARE rad2deg(FLOAT x)   REM Forward declare two inline
DECLARE deg2rad(FLOAT x)   REM assembly procedures
DEF key_entered AS STRING  REM STRING to hold selection character
DEF input_value AS FLOAT     REM FLOAT variable to hold input value

OPENCONSOLE

REM First, let's select which conversion we want to make
PRINT "Press 1 to convert degrees to radians"
PRINT "Press 2 to convert radians to degrees"
PRINT "Any other key to QUIT"
INPUT "Select: ", key_entered

REM Okay, let's enter a proper value for our selection
SELECT key_entered
 CASE "1"                             REM Convert degrees to radians
   INPUT "Enter degrees (0.0 to 180.0): ", input_value
     IF input_value >= 0.0 AND input_value <= 180.0
       deg2rad(input_value)
     ELSE
       PRINT "Incorrect value!" REM Must be between 0 and 180
     ENDIF

 CASE "2"                             REM Convert radians to degrees
   INPUT "Enter radians (0.0 to 1.0): ", input_value
     IF input_value >= 0.0 AND input_value <= 1.0
       rad2deg(input_value)
     ELSE
       PRINT "Incorrect value!" REM Must be between 0 and 1
     ENDIF
ENDSELECT

DO: UNTIL INKEY$ <> ""
CLOSECONSOLE
END

_asm
section .data
 deg_fmt db "Answer: %.16f degrees", 10, 0  ; C Runtime library
 rad_fmt db "Answer: %.16f radians", 10, 0    ; printing formats
 deg_per_pi dq 180.0                                    ; 180 degrees per pi radian
 result dq 0.0                                               ; Placeholder for DPFP results

section .text
 extern _printf                                ; Use C Runtime library function
                                                     ; to print results--has capability
rad2deg:                                         ; to print more precision to screen
 push ebp
 mov ebp, esp                                 ; Create stack to get passed parameter
 fldpi                                              ; Put pi on FPU stack
 fld qword [deg_per_pi]                   ; Put 180 on FPU stack
 fdiv st1                                         ; Divide 180 by pi
 fld dword [ebp+8]                         ; Load passed value onto FPU stack
 fmul st1                                       ; Multiply value by 180/pi
 fstp qword [result]                        ; Save answer and pop the FPU stack
 
 push dword [result+4]                   ; Load first 32-bits onto the stack
 push dword [result]                       ; Load next 32-bits onto the stack
 push dword deg_fmt                     ; C Runtime printing format
 call _printf                                    ; Print results to the screen
 add esp, 12                                  ; Remove parameters from stack
 mov esp, ebp                                ; Take down the stack
 pop ebp
ret                                                ; Return to IWBasic code

deg2rad:                                      ; Assembly procedure
 push ebp                                    ; Create stack to get at passed value
 mov ebp, esp
 fld qword [deg_per_pi]               ; Put 180 onto FPU stack
 fldpi                                          ; Put 16-digit pi onto FPU stack
 fdiv st1                                     ; Divide pi by 180 degrees
 fld dword [ebp+8]                     ; Load passed value onto FPU stack
 fmul st1                                    ; Multiply value by pi/180
 fstp qword [result]                     ; Save answer and pop the FPU stack

 push dword [result+4]              ; Load first 32-bits onto the stack
 push dword [result]                  ; Load next 32-bits onto the stack
 push dword rad_fmt                 ; C Runtime printing format
 call _printf                               ; Print results to 16-digit precision
 add esp, 12                             ; Remove parameters from stack
 mov esp, ebp                          ; Take down the stack
 pop ebp
ret                                            ; Return to IWBasic code
_endasm
REM -----------------------------------------------------------------------[/font]



This may not be what you want, but I typically employ inline assembly to get any additional precision I need for scientific calculations when I develop aeronautical simulations or climate models.

Note that you can get two constant values using these procedures. First, if you select 1 to convert degrees to radians and then enter 180 degrees, the answer will give you pi (3.141592653589793238462). Second, if you select 2 to convert radians to degrees and then enter 1 pi, the answer will give you 57.2957795130823230 degrees. Both are useful constants.

Logman
Education is what you get when you read the fine print.<br />Experience is what you get when you don't!

Egil

Thanks Logman!

I'll study your example thoroughly.
My greatest problem at the moment is that I have not done any EB/IWB coding in three years. Only a couple of easy demos using CB. But it was funny starting with IWB again though.

And to all the others:
As you can see, I returned from the hospital this afternoon, and so far everything has been successful. Except that my main email account is blocked. According to live.no (Microsoft), someone has probably hacket it. Every time I start my email client, I get a message from Microsoft saying my account has been used for irregular activities the last couple of days....
Support Amateur Radio  -  Have a ham  for dinner!

LarryMc

LarryMc
Larry McCaughn :)
Author of IWB+, Custom Button Designer library, Custom Chart Designer library, Snippet Manager, IWGrid control library, LM_Image control library

Egil

Thanks Larry.

Still having some trouble sitting, but I found a wooden box, put it on the kitchen table and placed my laptop on top. That way I can use the pc standing... In a week or two, I'll be fine.

Did some experiments today, using both the values Logman calulated with his exampe as constants for PI and Radians, and ckoehn's methods, angle calulations give exactly the same answers as a shareware program I tried (Orbitron at http://www.stoff.pl/).

But using PI=4*atan(1), as I did in the code posted at the start of this thread, produce large errors.
So maybe the IWB source for atan need another check?

Support Amateur Radio  -  Have a ham  for dinner!

GWS

Hi,

As far as I can tell, calculating pi = 4 * atan(1) gives the expected answer 3.141592653589793.

This is the best precision you can expect when you only have 8 bytes at your disposal for a decimal number.

You get 16 significant figures - anything more will be spurious digits   ::)

The value of pi to 100 digits is:

3.141592653589793238462643383279502884197169399375105820974944592307816406286

Some languages have what they refer to as an 'extended' data type, which is good for 19 significant figures by using 10 bytes, but I'm afraid 'double' is the best we can do.

all the best, :)

Graham

Tomorrow may be too late ..