I am writing a program that calculates Pi using the Nilakantha Series in a loop with an accuracy of at least 0.05%. The exit condition for this loop should be when the current calculated value res and the previously calculated value prev fit |res - prev| <= 0.0005. I’ve read up on some floating point comparisons in FASM, but still don’t exactly understand how it works. Currently the program just executes infinitely, never exiting the loop. During debugging I've seen floats often turn into 1.#IND00, which is supposed to be a NaN. How do I write an accurate comparison?
format PE console
entry start
include 'win32a.inc'
section '.code' code readable executable
; 3 + 4/(2*3*4) - 4 / (4*5*6) + 4/(6*7*8) - ...
start:
FINIT
piLoop:
; calculating denominator of fraction that will be added: x1*x2*x3
FLD [denominator]
FMUL [zero]
FADD [x1]
FMUL [x2]
FMUL [x3]
FSTP [denominator]
; changing denominator product values for next loop: x1 +=2, x2 += 2, x3 += 2
FLD [x1]
FADD [stepValue]
FSTP [x1]
FLD [x2]
FADD [stepValue]
FSTP [x2]
FLD [x3]
FADD [stepValue]
FSTP [x3]
;calculating numerator: multiplying numerator by -1
FLD [numerator]
FMUL [sign]
FSTP [numerator]
; calculating fraction: +-4 / (x1 * x2 * x3)
FLD [numerator]
FDIV [denominator]
FSTP [fraction]
; adding calculated fraction to our answer
FLD [res]
FADD [fraction]
FSTP [res]
; the comparison part, incorrect?
FLD [res]
FSUB [prev]
FABS
FCOM [accuracy]
FSTSW AX
SAHF
add [i], 1
; prev = res
FLD [res]
FSTP [prev]
jb endMet
jmp piLoop
endMet:
invoke printf, steps_string, [i]
invoke getch
invoke ExitProcess, 0
section '.data' data readable writable
steps_string db "Calculation completed. The Nilakantha Series took %d steps.",10,0
pi_string db "accurate pi = %lf, calculated pi = %lf", 10, 0
res dq 3.0
x1 dq 2.0
x2 dq 3.0
x3 dq 4.0
stepValue dq 2.0
fraction dq 0.0
numerator dq -4.0
denominator dq 0.0
sign dq -1.0
zero dq 0.0
N dd 20
i dd 0
accuracy dq 0.0005
calc dq ?
prev dq 3.0
section '.idata' import data readable
library kernel, 'kernel32.dll',\
msvcrt, 'msvcrt.dll',\
user32,'USER32.DLL'
include 'api\user32.inc'
include 'api\kernel32.inc'
import kernel,\
ExitProcess, 'ExitProcess',\
HeapCreate,'HeapCreate',\
HeapAlloc,'HeapAlloc'
include 'api\kernel32.inc'
import msvcrt,\
printf, 'printf',\
sprintf, 'sprintf',\
scanf, 'scanf',\
getch, '_getch'