Code archives/Algorithms/mathematical algorithms

This code has been declared by its author to be Public Domain code.

Download source code

mathematical algorithms by 5t@nKy2005
some mathematical algorithms
Here are some of my collections:

this is the 'heron-algorithm' with which you can get the square root from 'n'

Function Sqr#(n#)
   x0#=1
   repeat
      check#=0.5*(x0#+n#/x0#)
      x0#=x1#
   until check#=x0#
   return x0#
end function

this function is to get the greatest common divisor:

Function gcd(A,B)
   While B > 0
      R=A mod B
      A=B
      B=R
   Wend
   Return A
End Function

this function is to get the least common denominator and based on the gcd function

Function lcd(A,B)
   C=(A*B)/gcd(A,B)
   Return C
End Function

to get the factorial of a number you can use this

Function fac(n)
   check=1
   For i=1 To n
      check=check*1
   Next
   Return check
Emd Function

this function is to get the binomial coefficient, this is to get the number of Pascal's triangle (n choose k)

Function nCk(n,k)
   Return Fac(n)/(Fac(k)*Fac(n-k))
End Function

so that's it!

I hope it's useful and sorry for my bad english^^

Comments

Matty2005
Without actually testing it myself I would make the comment that with Heron's Algorithm it would be better to finish the repeat..until loop when abs(check-xo)<some small tolerance value as otherwise it could loop indefinitely for some values.


Floyd2005
Sometimes you have to be careful with integer arithmetic as well.
With large numbers A*B can 'overflow'. Here is an example of the problem and a corrected lcd().
big1 = 100000
big2 = 150000

Print gcd(big1, big2)
Print lcd(big1, big2)
Print lcd2(big1, big2)

WaitKey

Function gcd(A,B)
   While B > 0
      R=A Mod B
      A=B
      B=R
   Wend
   Return A
End Function

Function lcd(A,B)
   C=(A*B)/gcd(A,B)
   Return C
End Function

Function lcd2(A,B)
   Return A * ( B / gcd(A,B) )
End Function



TAS2008
Function fac(n)
check=1
For i=1 To n
check=check*1
Next
Return check
Emd Function

;should be
Function fac(n)
check=1
For i=1 To n
check=check*n
Next
Return check
End Function


degac2008
I think there's a type-error in the FAC function
Function fac(n)
   check=1
   For i=1 To n
      check=check*i
   Next
   Return check
End Function

Print "4! = "+fac(4)
Print "3! = "+fac(3)
Print "-1! = "+fac(-1)
Print "-4! = "+fac(-4)

Print "0! = "+fac(0)



Warpy2008
That works for me... factorial isn't really defined for negative numbers.


_PJ_2010
Lots of bugs in the original code. Some of it wont even compile, for example: "Emd Function"

Anyway, here's some fixed and optimised versions:
Function Fac%(n%)
	If(Not(n%))Then Return 0
	Local nReturn%=1
	Local nIter%=1
	For nIter%=1 To n%
		nReturn%=nReturn%*nIter%
	Next
	Return nReturn%
End Function

Function nCk%(n%,k%)
	If (k%>0) And (k<n%) Then Return Fac(n%)/(Fac(k%)*Fac(n-k%))
	Return 0
End Function

Function Gcd%(A%,B%)
	Local n%=0
	If (B%<1) Then Return 0
	While (B%)
		n=A% Mod B%
		A%=B%
		B%=n%
	Wend
	Return A%
End Function


I'm not sure what "your" Heron's algorithm is trying to do, but as it stands, it doesn't even follow Heron's formula or stops itself from looping to infinity. You have thrown in values like x1# for no reason whatsoever. Thus it fails on pretty much everything.

Recommend using Heron's ACTUAL algorithm:

fCurrent#=0.5*(fLast#+(n%/fLast#))

Using this formula limited by n iterations (It should never need that many, but makes a good prevention of infinite loops) gives a pretty good return.
Dunnno whether it's faster or slwoer than Blitz' default Sqr() or even, whether or not it gives as good accuracy.

Function Sqrt#(n%)
	Local fCurrent#=n%
	Local fLast#=0.5*(fCurrent#+(n%/fCurrent#))
	Local nIter%=1
	While ((nIter)*(nIter%<n))
		nIter%=nIter%+1
		fCurrent#=0.5*(fLast#+(n%/fLast#))
		fLast#=fCurrent#
	Wend
	Return fLast
End Function


Note for future reference: Test your code a bit before submitting it ;)


Floyd2010
This all needs to be done more carefully.

First a minor fix, Fac(0) should return 1. That is by definition.

As with the lcd function the intermediate calculations can easily overflow even if the final result is reasonably small. For example, nCk( n, 2 ) should always be n*(n-1)/2. Thus nCk( 21, 2 ) is 21*20/2 = 210. There is no reason to fool around with huge numbers like Fac(21)/Fac(19) just to get 21*20.

Also notice the symmetry with nCk( n, k ) = nCk( n, n - k ). We don't need to calculate nCk( 21, 19 ) directly because we know it is the same as nCk( 21, 2 ).

Anyhow, here's the right way to calculate nCk, which I have renamed nCr to match the way it is usually named on scientific calculators.

Note for example that nCr( 21, 2 ) returns 210 as it should.
The original nCk( 21, 2 ) manages to produce -5.

Function nCr( n, r )  ; binomial coefficient "n choose r"
	If r > n/2 Then Return nCr( n, n - r )
	c = 1
	For d = 1 To r
		c = ( c * ( n +1 - d ) ) / d
	Next
	Return c
End Function



_PJ_2010
Thanks, Floyd.


Code Archives Forum