Recursive factorial output - vb.net

I'm trying to write a recursive function through a vb console application that will output the factorial or a number between 1 and 10. I get a System.StackOverflowException when I run it. Can anyone help explain what I've done wrong?
Module Module1
Dim Number As Byte
Sub Main()
Console.WriteLine("Write a number from 1-10")
Number = Console.ReadLine()
FactorialCalc()
End Sub
Function FactorialCalc()
Dim Counter As Byte
Dim A As Byte
' Dim Factorial As Integer
Do
If Number < 1 Or Number > 10 Then
Console.WriteLine("Please select a number from 1-10")
End If
Loop Until Number >= 1 And Number <= 10
A = Number
Do
FactorialCalc = Number * FactorialCalc(Number - 1)
Counter = Counter + 1
Loop Until Counter = A + 1
Console.WriteLine(FactorialCalc.value)
Console.ReadLine()
End Function
End Module

A factorial program shouldn't be all this long. All you need is:
Module Module1
Dim Number As Integer
Sub Main()
Do
Console.WriteLine("Write a number from 1-10")
Number = Console.ReadLine()
Loop Until Number >= 1 And Number <= 10
Dim Result = FactorialCalc()
Console.WriteLine(Result)
Console.ReadLine()
End Sub
Function FactorialCalc(num as Integer) As Integer
Return num * If(num > 2, FactorialCalc(num - 1), 2)
End Function
End Module

your recursive call to FactorialCalc(Number - 1) is going to keep getting called endlessly, there by exhausting your stack space. The condition to break out of the recursion is after your recursive call and so control never reaches the point beyond the call to the recursive function and keeps calling it over and over again.

Related

How can I solve my "sub main was not found" problem?

Module PrimePairs
Public Function IsPrime(n As Long) As Boolean
Console.WriteLine("Please enter the value: ")
n = Console.ReadLine()
n = Math.Abs(n) ' Allows to consider negative prime numbers
If n < 2 Then ' Disallows -1, 0, 1
Return False
End If
Dim i As Long
i = 2
While i < n ' Note that for n = 2 we don't enter the loop and thus return True.
If n Mod i = 0 Then
Return False
End If
i += 1
End While
Return True
End Function
Public Function PrimePairs(ByVal n As Long, ByVal n2 As Long) As Integer
Dim count As Integer = 0
Console.ReadLine()
If n Mod 2 = 0 Then
For i = 1 To (n / 2) + 1
n2 = n - i
If IsPrime(i) And IsPrime(n2) = True Then
count += 1
End If
Next
Else
n2 = n - 2
If IsPrime(n2) = True Then
count = +1
End If
End If
Console.WriteLine("The result is:", count)
Return n
End Function
End Module
I want my code to calculate how many prime number twins can write the input I gave.
The problem is that your project actually does not contain a Sub Main(), as the error states.
You defined two functions in the Module Program, but console applications need a predefined entry point, which usually is the Main method.
The compiler is telling you that your project is not valid because it didn't find any entry point.
Just add a Sub Main() to get your project working, then call your functions from that method.
Example:
Option Strict On
Module Program
Sub Main(args As String())
Console.WriteLine("Please enter the value: ")
Dim input As String = Console.ReadLine()
Dim number As Long
If Long.TryParse(input, number) Then // More about this function in the answer below
Dim prime As Boolean = IsPrime(number)
If prime Then
Console.WriteLine(number & " is prime.")
Else
Console.WriteLine(number & " is not prime.")
End If
End If
Console.ReadLine()
End Sub
Function IsPrime(n As Long) As Boolean
n = Math.Abs(n) ' Allows to consider negative prime numbers
If n < 2 Then ' Disallows -1, 0, 1
Return False
End If
Dim i As Long = 2
i = 2
While i < n ' Note that for n = 2 we don't enter the loop and thus return True.
If n Mod i = 0 Then
Return False
End If
i += 1
End While
Return True
End Function
End Module
Also, I suggest you to enable Option Strict On as I added at the beginning of file. This prevents the compiler from doing implicit casts and forces you to explicitly declare your variables.
E.g., your line of code
n = Console.ReadLine()
is not valid with Option Strict On, because n is supposed to be a long, but Console.ReadLine() returns a string.
If you are a beginner, this will allow you to better understand how programming works and will help you to avoid errors - take good habits from the beginning, you can thank me later ;)
That's why I changed your code withLong.TryParse(input, number): this function returns true if provided input can be cast (=converted) to a long, and assigns the casted value to number variable.
There's a lot more I'd like to suggest you, but I would go off-topic.

Does this code not work because it will take a long time or is it broken?

I am currently trying to generate random numbers until a user defined amount of identical numbers in a row appears. The numbers range from 1 to 10.
When I want 8 identical numbers in a row it takes between 3 and 5 seconds. It goes through about 5 million random numbers. When I want 9 in a row I have left it for over 45 minutes without any luck.
I thought it would only take about 10 times the amount of time as it did for 8 since 1/10 to the power of 9 is only ten times bigger than to the power of 8.
Is it a problem with my code or have I messed up the maths?
MY CODE:
Sub Main()
Console.WriteLine("how many identical numbers in a row do you want")
Dim many As Integer = Console.ReadLine
Dim storage(many - 1) As Integer
Dim complete As Boolean = False
Dim part As Integer = 0
Dim count As Integer = 0
Randomize()
While complete = False
count += 1
storage(part) = Int(Rnd() * 10) + 1
' Console.WriteLine(storage(part))
part += 1
If part = many Then
part = 0
End If
If storage.Min = storage.Max Then
complete = True
End If
End While
Console.WriteLine("===========")
Console.WriteLine(count.ToString("N"))
Console.WriteLine("===========")
For i = 0 To many - 1
Console.WriteLine(storage(i))
Next
Console.ReadLine()
End Sub
There is more than one possibility: it could be that the VB Rnd function is written so that it can never work, or it could be that it really does simply take a long time sometimes. You would have to do many trials and average them out to find out if your expected ratio of 1:10 works as expected.
Incidentally, you don't need to keep the last ten numbers. You can just keep a count of how many times the next random number equals the previous number. Also I suggest trying a different RNG (random number generator), for example the .NET one:
Module Module1
Dim rand As New Random()
Sub Main()
Console.Write("How many identical numbers in a row do you want: ")
Dim howMany As Integer = CInt(Console.ReadLine)
Dim count As Long = 0
Dim previous = -1
Dim soFar = 0
Dim n = 0
While soFar < howMany
count += 1
n = rand.Next(1, 11)
'Console.Write(n.ToString() & " ")
If n = previous Then
soFar += 1
Else
'If previous >= 0 Then
' Console.WriteLine(" X")
' Console.Write(n.ToString() & " ")
'End If
previous = n
soFar = 1
End If
End While
Console.WriteLine()
Console.WriteLine("Tries taken: " & count.ToString())
Console.ReadLine()
End Sub
End Module

Im trying to do an if statement for a console game in Vb

Module Module1
Sub MoveLeft()
Console.WriteLine("You Moved Left")
End Sub
Sub MoveRight()
Dim Number As String
Console.WriteLine("You Moved Right")
Randomize()
Number = Int(Rnd() * 10) + 1
If Number = 1 To 2 Then
Console.WriteLine(" An Enemy Appeared")
ElseIf
Console.WriteLine(" The Way Is Clear")
End If
End Sub
Sub Shoot()
Console.WriteLine("Pew")
End Sub
Sub Main()
Dim quit As Boolean = False
Dim key As String = ""
Do While quit = False
If Console.KeyAvailable Then
key = Console.ReadKey(0).Key
If key = 81 Then
quit = True
End If
Select Case key
Case 37
MoveLeft()
Case 39
MoveRight()
Case 32
Shoot()
End Select
End If
Loop
End Sub
End Module
How do I Get A random Number To roll and make certain values make an enemy appear and other values not.
Instead of
Randomize()
Number = Int(Rnd() * 10) + 1
If Number = 1 To 2 Then
Console.WriteLine(" An Enemy Appeared")
ElseIf
End If
Try
Dim rnd As New Random
Select Case rnd.Next(5)
Case 1
Console.WriteLine(" An Enemy Appeared")
Case Else
Console.WriteLine(" The Way Is Clear")
End Select
This code creates a new randomized randomnumber generator called rnd, generates a random number between 1 and 5 inclusive and if the random number is 1 then an enemy appears. If the random number is anything else, the way is clear.
You only need a range of 5 and a check to see if the result is 1 as this is the same as a range of 10 and checking for a result of 1 or 2
Although speed of computation isn't too important in your program, I think that using a Select Case statement may be quicker than your original code - and is more maintainable later on
' Initialize the random-number generator.
Randomize()
' Generate random value between 1 and 10.
Dim number As Integer = CInt(Int((10 * Rnd()) + 1))
' Show enemy if the integer number is smaller than 3 (= 1, 2)
If number < 3 Then
'your method here to have enemy appear
Else
Console.WriteLine(" The Way Is Clear")
End If

How to represent a number in the form of A*10-^n?

I recently wrote this program in Visul Basic 13.
it searchs for the nth catalan number but after 48 even Decimal type is too short.
Is there any other way to represent them? like in the form of A*10^n?
Public Class Try_Catalan_Number
'Catalan numbers form a sequence of natural numbers that occur in various counting problems,
'often involving recursively defined objects.
Inherits Base_Number
Public Overrides Sub Test()
Dim Return_Catalan_Value As Decimal
If Function_Catalan(Return_Catalan_Value) = False Then
Return_To_Form_Boolean = False
Else
Return_To_Form_Boolean = True
End If
Return_To_Form_Value = Function_Catalan(Return_Catalan_Value)
End Sub
Private Function Function_Catalan(Return_Catalan_Value As Decimal) As Decimal
'We return a Decimal function because catalan numbers can be very big and decimal is the biggest type.
Dim Binomial_Cofficients As Decimal
Dim Result As Decimal
Dim Number_Of_Loops As Integer
Dim tmpNumber As Object
Dim K As Decimal
Dim N As Decimal
If (Number > 48) Then
Return False
Exit Function
End If
'48 is the largest catalan number position which can be displayed...any position above 48 is too big.
tmpNumber = Number - 1
N = 2 * tmpNumber
K = tmpNumber
Result = 1
For Number_Of_Loops = 1 To K
Result = Result * (N - (K - Number_Of_Loops))
Result = Result / Number_Of_Loops
Next Number_Of_Loops
Binomial_Cofficients = Result
tmpNumber = Number - 1
tmpNumber = ((1 / (1 + tmpNumber)) * Binomial_Cofficients)
Return_Catalan_Value = tmpNumber
Return Return_Catalan_Value
End Function
End Class
[I assume by "Visul Basic 13" you mean the VB which is associated with Visual Studio 2013, i.e. VB version 12.0.]
You can use System.Numerics.BigInteger (you'll have to add a reference to System.Numerics):
Imports System.Numerics
Module Module1
Friend Function Factorial(n As Integer) As BigInteger
If n < 2 Then Return 1
If n = 2 Then Return 2
Dim f As BigInteger = BigInteger.Parse("2")
For i = 3 To n
f *= i
Next
Return f
End Function
Friend Function CatalanNumber(n As Integer) As BigInteger
Return Factorial(2 * n) / (Factorial(n + 1) * Factorial(n))
End Function
Sub Main()
For i = 0 To 550
Console.WriteLine(CatalanNumber(i).ToString())
Next
Console.ReadLine()
End Sub
End Module
I did not test to see the maximum Catalan number it can calculate, and I have no inclination to verify the results beyond those shown on the Wikipedia page.
Optimisations are left as an exercise for the reader ;)
Edit: FWIW, I can get it to run a bit faster by using
Function CatalanNumber(n As Integer) As BigInteger
Dim nFactorial = Factorial(n)
Dim twonFactorial = nFactorial
For i = (n + 1) To 2 * n
twonFactorial = BigInteger.Multiply(twonFactorial, i)
Next
Return twonFactorial / (BigInteger.Pow(nFactorial, 2) * (n + 1))
End Function
The speed increase varies from roughly 50% (n=50) to 20% (n=5000). If you're only using the function a few times for fairly small n, there may be little point worrying about it.
Edit2 Re-writing your function a bit to make it easier to read and removing the off-by-one error, we get:
Private Function Function_Catalan(a As Integer) As BigInteger
If a = 0 Then Return 1
Dim binomialCofficient As BigInteger = BigInteger.One
Dim n As Integer = 2 * a
Dim k As Integer = a - 1
For i As Integer = 1 To k
binomialCofficient = binomialCofficient * (n - (k - i)) / i
Next i
Return binomialCofficient / a
End Function
to get this format you could use:
String.Format("{0:E4}", InputNumber)

How is the code going to calculate only the wanted value for n?

I am struggling with this code that I Have to do about calculating the nth term of the Fibonacci series. The program is supposed to take the
value of n and return the corresponding nth Fibonacci number.If the function is given an
invalid n value, it should return -1.
For now, I been trying to make this work, and after 5 hours and 45 minutes sitting on the computer with no ideas how to make this work, here I am asking for help.
Any feedback would be greatly appreciated
Here is what i got so far:
Module Module1
Function Fibonacci(ByVal n)
If n < 2 Then
Return n
Else
Return Fibonacci(n - 1) + Fibonacci(n - 2)
End If
If n < 0 Then
Return Val(-1)
End If
End Function
Sub Main()
Dim n As Double
Console.WriteLine("Welcome!!!")
Console.WriteLine(" Please Enter the nth term You Would like to Find ")
n = Console.ReadLine()
For n = 1 To 30
Console.WriteLine(Fibonacci(n))
Next
Console.ReadKey()
End Sub
End Module
Module Module1
Function Fibonacci(ByVal n)
If n < 2 Then
Return n
Else
Return Fibonacci(n - 1) + Fibonacci(n - 2)
End If
End Function
Sub Main()
Dim n As Double
Console.WriteLine("Welcome!!!")
Console.Write(" Please Enter the nth term You Would like to Find ")
n = Console.ReadLine()
If n < 0 Then
Console.WriteLine("-1")
Else
For i As Integer = 1 To n
Console.WriteLine(Fibonacci(i))
Next
End If
Console.ReadLine()
End Sub
End Module