Random number in c# which should be exactly random every time? - c#

i am trying to generate random number for my mental math quiz game. But i think i am doing something wrong.Please help me to correct my code.Please try to include some sort of explanation, why my code is incorrect. Thanks in advance!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MindTraining
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter the digits of first number ");
int a=int.Parse(Console.ReadLine());
Console.WriteLine("Enter the digits of second number");
int b = int.Parse(Console.ReadLine());
Random RandomClass = new Random(DateTime.UtcNow.Second);
int RandomNumber = RandomClass.Next(10^(a-1), 10^a);
Console.WriteLine(RandomNumber);
}
}
}
What i am trying to achieve is , I want user to enter number of digits in number a and number of digits in number b
Then program would generate random number, say user entered 2 for a ,then program have to generate numbers between 0 to 10(Random Number, Every time different)
if user entered 3 for a, then between 10 to 100,
Similar thing for b, and then calculating product.Number should not repeat more than 2 times, during program run time.
Ok, i changed my code to
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MindTraining
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter the digits of first number ");
int a=int.Parse(Console.ReadLine());
Console.WriteLine("Enter the digits of second number");
int b = int.Parse(Console.ReadLine());
Random RandomClass = new Random(DateTime.UtcNow.Second);
double num1=Math.Pow(10,a-1);
double num2=Math.Pow(a,1);
int num3 = Convert.ToInt32( num1);
int num4=Convert.ToInt32(num2);
int RandomNumber = RandomClass.Next(num3,num4);
Console.WriteLine(RandomNumber);
}}
// But still not getting result, I throws error,
This one worked!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace MindTraining
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Enter the digits of first number ");
int a=int.Parse(Console.ReadLine());
Console.WriteLine("Enter the digits of second number");
int b = int.Parse(Console.ReadLine());
Random RandomClass = new Random();
double num1=Math.Pow(10,(a-1));
double num2=Math.Pow(10,(a));
int num3 = Convert.ToInt32( num1);
int num4=Convert.ToInt32(num2);
int RandomNumber = RandomClass.Next(num3,num4);
Console.WriteLine(RandomNumber);
}
}
}

^ is not a raise to the power operator in c#.
Use Math.Pow for this.

The ^ operator in C# means "exclusive or" (XOR), not exponentiation. Read about it here: http://www.dotnetperls.com/xor . Try Math.Pow instead.

is there any reason you want to use a seed value that is so limited? Why not use
Random RandomClass = new Random();
which takes a default time based seed value for your object?
Also, use Math.pow(base,exp) to calculate the range for your Random.next() calls as:
int RandomNumber = RandomClass.Next((int)Math.Pow(10,(a-1)), (int)Math.Pow(10,a));
In your code, the error occurs because,
double num2=Math.Pow(a,1);
returns a itself. So, your maxvalue in the Random.next() is lower than your minvalue, which is logically incorrect. This is the error, I got from running your code, that is apart from the fact that you are missing a closing brace at the end.
Also, you must realise that there is no such thing as a perfectly random number generator. All these are pseudo-random generators. They follow the normal distribution of numbers on the number line. So, to say that a number will not be generated more than twice in one execution is not feasible unless you store all the numbers generated and keep checking against them. This should be a last resort, only is case of dire requirements.

While generating a TRULY random number you cannot suppose that the number is different all the time,hope you got the point. So you need to additionally make sure that the number is different each time.

Related

Could someone explain why Converting to int and using read line instead of Read fixed my issue?

So previous I was having a ton of trouble with finding the difference between a randomly generated number and user input. I did a little search and found that I couldn't use Console.Read(); and that I actually had to use this int guess = Convert.ToInt32(Console.ReadLine()); While playing around with it i accidentally made it Convert.ToInt32(Console.Read()); which was in turn making the math completely wrong. Apologies if I'm not explaining myself effectively I'm new to coding and this was meant to be something to learn from. Thanks!
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Would you like to play the guessing game?");
string input = Console.ReadLine();
if (input.Equals("yes"))
{
Console.WriteLine("Alright! The rules are simple, i'll think of a number and you guess it!");
Console.WriteLine("Alright enter your guess: ");
int guess = Convert.ToInt32(Console.ReadLine());
Random rand = new Random();
int answer = rand.Next(1,11);
if (rand.Equals(guess))
{
Console.WriteLine("Congratulations you guessed correctly!");
}
else
{
Console.WriteLine("Aww you were so close! I guessed " + answer);
int difference = guess - answer;
Console.WriteLine("you were only " + Math.Abs(difference) + " away");
}
} else
{
Console.WriteLine("Closing application...");
Thread.Sleep(1000);
Environment.Exit(0);
}
}
}
}
Console.Read()
Returns you the ascii value of a single character being input.
For example, entering 'A' would return 65. See here for a list of ascii codes. Note that the ascii value for 1 is actually 49.
Convert.ToInt32(Console.ReadLine());
Reads the entire line and tries to convert it to an integer.
Console.Read() will grab just one character and Console.ReadLine() takes the whole line or everything the user types until it found the "Enter" key pressed.
Becuase Console.Read reads in characters from the console. It returns, as an integer. So when you enter "yes" the output will be
121 = y
101 = e
115 = s
13 =
10 =
The final two characters (13 and 10) are equal to the Windows newline.

Mono Getting the same sequence using Random

When I run the following code in Mono (and not in Microsoft's C# apparently) in the monodevelop IDE. I get the same sequence of random numbers every time (00111111110110001001). If I change the range to something else e.g. r.Next(0, 5) then I do get random values. This seems very weird to me .. is this a bug or am I doing something dumb?
NOTE: it seems sometimes these numbers are negated.. e.g. I see 11000000001001110110 occasionally.
using System;
namespace TestRNG
{
class MainClass
{
public static void Main (string[] args)
{
Random r = new Random ();
for (int i = 0; i < 20; i++) {
Console.Write(r.Next(0, 2));
}
Console.WriteLine();
}
}
}
This is not the "Calling Next() on instances of Random called too closely together and therefore seeded with the same seed from the system clock problem".
Using the following code:
using System;
namespace TestRNG
{
class MainClass
{
public static void Main (string[] args)
{
Random r = new Random (Guid.NewGuid().ToByteArray()[0]);
for (int i = 0; i < 20; i++) {
int rn = r.Next ();
Console.WriteLine(rn + " " + (rn % 2));
}
Console.WriteLine();
}
}
}
I see that I get different values for rn every time but the sequence of values for rn % 2, which is what I suspect r.Next() is returning, is the same old values I always see. This leads me to believe that the Russian? fellow who posted an answer before and was down-voted to oblivion was correct (he's subsequently removed his answer). See http://eternallyconfuzzled.com/arts/jsw_art_rand.aspx for example.
Based on one of the comments below this may only be a mono implementation thing.
Well, extending on what swistak said(because i used the Guid class too), this is the code i made for your issue, is already tested and it works:
using System;
using System.Linq;
namespace pruebaDeNumerosAleatorios
{
class MainClass
{
public static int RandomNumber()
{
Random x = new Random(Guid.NewGuid().ToByteArray().First());
return x.Next(0, 20);
}
public static void Main(string[] args)
{
for (int i = 0; i < 20; i++)
Console.WriteLine(RandomNumber());
}
}
}
As it was said before, you don't give the time to the internal clock (which you are using as seed) to change between iterations so, the number generated is the same. What i did here is implement the Guid class which generates a 'unique' number, convert it as an array of bytes and just used the first element of the array as seed.
i did this in a method because that guarantees me that everytime the method is called a diferent number is generated by the Guid class, so im using a different seed for the random number.
You can generate "more random" number without much higher impact on performance by using Guid class:
Random r = new Random(Guid.NewGuid().ToByteArray()[0]);
Edit: The problem with getting similar values every time is because Random.Next() is taking value from current system clock, so probably there isn't much difference in time between each compilation to generate varied values. Try running your code in a loop and values should be more varied.

C# Variable int assumes a different value

I'm trying to create a simple program to calculate an average. The user should enter a positive number, then I create a loop to sum from 0 to the number entered. Then the average is the total divided by the number entered.
Problem: When I enter a number, for example, 10, the variable becomes 58. To any value that I enter, it always adds 48. Anyone have a clue about this issue?
Here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace inClass1
{
class Loops
{
static void Main(string[] args)
{
int total = 0;
int num;
Console.Write("Enter a positive number: ");
num = Convert.ToInt32(Console.Read());
for (int i = 0; i <= num; i++)
{
total = total + i;
}
double average = total / (double)num;
Console.WriteLine("The average is = " + average);
Console.ReadLine();
}
}
}
It's because Console.Read method reads the first char and returns its ASCII value. And it only reads one char, so you can't read more than one number at the same time. To fix that just use Console.ReadLine to take a string as input:
um = Convert.ToInt32(Console.ReadLine());
In case where the user inputs an invalid number this will fail. To prevent that you can look into int.TryParse method.
The problem is that you are using Console.Read.
That method returns a int, not a string. That int is the Unicode character code of the read character. The overload of Convert.ToInt32 that takes a int looks like this:
public static int ToInt32(int value) {
return value;
}
(Reference Source)
Which means that its just returning the passed value (instead of parsing). Unicode '1' is the number 49.
Instead, use Console.ReadLine which in addition to getting the whole input (not just the first character) will return a string, so that int.Parse is called on it instead of casting when you use Convert.ToInt32.

Random not getting its max value

I am trying to create a console application which is basically a very simple version of a security measure used by some websites and banks etc.
The user will have declared a "Secret Word"(stored in a stringBuilder), after which, every time the user tries to access the program/website etc they have to enter character X of the word (X generated via a random). However, the random never selects the last character of the word.
Example: When i use a 2 letter Secret word, it will only ever select the first letter, when i have tried getting it to select the letter by other methods it thinks that there is a letter 0 which throws the whole application.
Why is the final character never being selected? please help (new to c#)
Code Below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace randomCharSelecter
{
class Program
{
static void Main(string[] args)
{
StringBuilder stringBuilder = new StringBuilder();
Console.WriteLine("Please Enter Your Secret Word");
stringBuilder.Append(Console.ReadLine());
EnterInput:
Random rndSelect = new Random();
int randomChar1 = rndSelect.Next(1, (stringBuilder.Length));
Console.WriteLine("Please enter character {0} of your secret word", randomChar1);
string userInput = Console.ReadLine();
if (userInput == (Convert.ToString(stringBuilder).Substring(randomChar1 - 1, 1)))
Console.WriteLine("Correct!");
else
{
Console.WriteLine("Incorrect! Please try again");
goto EnterInput;
}
Console.ReadLine();
}
}
}
This is the expected behavior. From the documentation:
Return Value
Type: System.Int32
A 32-bit signed integer greater than or equal to minValue and less than maxValue; that is, the range of return values includes minValue but not maxValue. If minValue equals maxValue, minValue is returned.
In other words if you want a random integer between 1 and stringBuilder.Length, inclusive (that is, that the result could possibly equal stringBuilder.Length), you need to use:
int randomChar1 = rndSelect.Next(1, stringBuilder.Length + 1);
Alternatively, you could simply modify the code to make use of zero-based indexing:
int randomChar1 = rndSelect.Next(0, stringBuilder.Length);
...
if (userInput == (Convert.ToString(stringBuilder).Substring(randomChar1, 1)))
Console.WriteLine("Correct!");
Your problem is that the second value of Random.Next(int val1, int val2) is end-exclusive. So you'll end up having to do stringBuilder.Length + 1
Source: http://msdn.microsoft.com/en-us/library/2dx6wyd4(v=vs.110).aspx

I am getting this error when compiling my program. Operator " + " cannot be applied to operands of "System.Random" and "System.Random"

I am trying to generate random numbers for math problems. When the program is compiled the error Operator " + " cannot be applied to operands of type 'System.Random' and 'System.Random. I really dont know how to fix this error.
Random num1 = new Random(0);
Random num2 =new Random(0);
int rand;
Console.Write("What is");
Console.Write(num1);
Console.Write( " - ");
Console.Write( num2);
Console.Write( "?");
int answer = Console.Read();
if (num1 + num2 == answer) ERROR {
Console.Write(" Your are Correct!\n");
correctCount++;
}
else
Console.Write( "Your answer is wrong" );
Console.Write(num1);
Console.Write(" + ");
Console.Write(num2);
Console.Write("should be ");
Console.Write(num1 + num2); ERROR
count++;
}
}
}
}
Now i am able to compile the program without any errors, but it is not generating any numbers. Does anyone see what i may have donwe wrong.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
namespace Jagtutor
{
[Activity(Label = "Addition")]
public class AdditionsActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Create your application here
SetContentView(Resource.Layout.Second);
var label = FindViewById<TextView>(Resource.Id.screen3Label);
label.Text = Intent.GetStringExtra("ModuleData") ?? "Data not available";
{
int correctCount = 0;
int count = 0;
while (count < 10);
{
Random gen = new Random();
int num1 = gen.Next();
int num2 = gen.Next();
Console.Write("What is");
Console.Write(num1);
Console.Write( " - ");
Console.Write( num2);
Console.Write( "?");
int answer = Int32.Parse(Console.ReadLine());
if (num1 + num2 == answer) {
Console.Write(" Your are Correct!\n");
correctCount++;
}
else
Console.Write( "Your answer is wrong" );
Console.Write(num1);
Console.Write(" + ");
Console.Write(num2);
Console.Write("should be ");
Console.Write(num1 + num2);
count++;
}
}
}
}
}
You misunderstood the way Random is used: it is not a number, it is a class that can be used to generate random numbers.
Try this:
// Make a generator
Random gen = new Random();
// Now we can use our generator to make new random numbers like this:
int num1 = gen.Next();
int num2 = gen.Next();
Every time you call gen.Next() you get a new random number. If you would like the sequence of random numbers to be repeatable, pass a number (any number) to the constructor of the Random. Beware that every time you run your program the result will stay the same.
There are quite a few issues with the code snippet you pasted. I'd suggest (if you haven't already) investing in a decent beginning C# book. Generating random numbers, in fact, is one of the most popular "example programs" you find in those kinds of books. However, to get you started, here's some key points:
When you paste sample code to a site like this, make sure it is a short, self-contained, correct example. Even if we fix the compiler error in your code, there are several other issues with it, including unbalanced and/or missing braces. Start simple and build your example up until you get the error, then paste that code. Note that a good 75% of the time this will help you fix the error yourself. For example, if you removed the lines of code that did not compile, and just ran the first part, it would print out "What is System.Random - System.Random?", which should give you a pretty clear idea that your num1 and num2 are not what you thought they were.
As the rest of the answers here have pointed out, you have a fundamental misunderstanding of how the C# Random class works. (Don't feel bad, computer-generated "random numbers" make no sense to anyone until someone explains them to you.) The solution provided in those answers is correct: Random is a random number generator, and you need to call one of the Next functions on your instance to get an integer from it. Also, you usually will not want multiple instances of Random unless you actually want to produce the same random sequence more than once. The MSDN article has a very thorough example.
While not "wrong" per-se, you're not being very efficient with your console output. Console's read and write functions operate entirely on string objects, and they have built-in composite formatting capabilities. For example, your first few lines of code could be rewritten as:
var random = new Random();
var x = random.Next();
var y = random.Next();
Console.Write("What is {0} + {1}? ", x, y);
As I mentioned in my comment, Console.Read() is not the correct function to read in complete user input; it returns data a single UTF-16 character at a time. For example, if the user typed in 150 you would get 49, 53, and 48, in that order. Since you presumably want to allow the user to type in more than one digit at a time, you should instead called Console.ReadLine(), which returns the entire string, then convert that to an integer using Int32.Parse() or some similar function.
You are trying to add two random generators not random numbers, use this:
Random randomGenerator = new Random(0);
var num1 = randomGenerator.Next();
var num2 = randomGenerator.Next();
You need to call one of the overloads of Random.Next() http://msdn.microsoft.com/en-us/library/9b3ta19y.aspx to get the actual random number.

Categories