0

hello im trying to do this calculation : [365!/((365^x)((365-x)!))] the problem is when i do it it doesn't give me the decimals just the integer it give me 0 or 1 because the answer is 0

Public Class Form1
    Private Function fact(ByVal n As Integer) As Numerics.BigInteger
        Dim Z As New Numerics.BigInteger(1)
        For i As Integer = 1 To n
            Z = Z * i
        Next
        Return Z
    End Function

    Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
        Dim min As Integer
        Dim max As Integer
        Dim ranum As Integer
        Dim ind() As Integer
        Dim ran As New Random
        Dim F365 As New Numerics.BigInteger(0)
        F365 = Numerics.BigInteger.Parse("25104128675558732292929443748812027705165520269876079766872595193901106138220937419666018009000254169376172314360982328660708071123369979853445367910653872383599704355532740937678091491429440864316046925074510134847025546014098005907965541041195496105311886173373435145517193282760847755882291690213539123479186274701519396808504940722607033001246328398800550487427999876690416973437861078185344667966871511049653888130136836199010529180056125844549488648617682915826347564148990984138067809999604687488146734837340699359838791124995957584538873616661533093253551256845056046388738129702951381151861413688922986510005440943943014699244112555755279140760492764253740250410391056421979003289600000000000000000000000000000000000000000000000000000000000000000000000000000000000000000")
        min = Integer.Parse(Tmin.Text)
        max = Integer.Parse(Tmax.Text)
        ranum = Integer.Parse(TRan.Text)
        ReDim ind(ranum)
        For x As Integer = 1 To ranum
            ind(x) = ran.Next(min, max + 1)
            Answer.Items.Add(ind(x))
        Next
        Dim P(ranum) As Numerics.BigInteger
        Dim facts(ranum) As Numerics.BigInteger
        For x = 1 To ranum
            P(x) = 365 ^ (ind(x))
            facts(x) = fact(365 - ind(x))
        Next
        Dim phenB(ranum) As Numerics.BigInteger
        Dim phen(ranum) As Double
        For x = 1 To ranum
            phenB(x) = (P(x) * facts(x))
            phen(x) = F365 / phenB(x)
            tx.Text = phen(x)  (here is the aswer)
        Next

    End Sub
End Class
Thomas
  • 13
  • 4

1 Answers1

0

The BigInteger class does not have a function to give a non-integer result for division. However, it does have BigInteger.Log, so, using these logarithmic identities:

  • ln(a⋅b) = ln(a) + ln(b)
  • ln(a/b) = ln(a) - ln(b)
  • ln(a^b) = b⋅ln(a)

we can perform the calculation like this:

Function SomeCalc(n As Integer) As Double
    Dim lnF365 = BigInteger.Log(fact(365))
    Dim lnPower = n * Math.Log(365)
    Dim lnOtherFact = BigInteger.Log(fact(365 - n))

    Return Math.Exp(lnF365 - lnPower - lnOtherFact)

End Function

where fact() is a pre-calculated array:

Option Strict On
Option Infer On
' ... other code ...

Dim fact(365) As BigInteger

' ... other code ...

Private Sub CalcFacts()
    Dim z = BigInteger.One
    For i = 1 To 365
        z *= i
        fact(i) = z
    Next
End Sub

You could even have an array of pre-calculated logs of the factorials, instead of an array of the factorials. It depends on if you're using them elsewhere, and if there is any need for it to go a tiny tiny bit faster:

Function SomeCalc(n As Integer) As Double
    Dim lnF365 = lnFact(365)
    Dim lnPower = n * Math.Log(365)
    Dim lnOtherFact = lnFact(365 - n)

    Return Math.Exp(lnF365 - lnPower - lnOtherFact)

End Function

and

Dim lnFact(365) As Double
' ...
Private Sub CalcLnFacts()
    Dim z = BigInteger.One
    For i As Integer = 1 To largestNum
        z *= i
        lnFact(i) = BigInteger.Log(z)
    Next
End Sub

That number 365 should be a named variable - I had no idea what a sensible name for it would be.

Andrew Morton
  • 24,203
  • 9
  • 60
  • 84
  • thanks the logarithm solution worked perfectly i should code more i knew about it but i didn't thik to use it in this situation i need more experience and for whoe is asking the random is because im making an Evolutionary algorithm – Thomas Apr 04 '20 at 22:47
  • 1
    @Thomas the best way to thank someone on Stack Overflow is to accept their answer by clicking the check mark (tick mark) to the left of their answer. When you have enough reps you can also upvote the answer with the little triangle above the number. Upvotes are for especially helpful and complete answers. – Mary Apr 04 '20 at 23:56