I'm trying to calculate the cumulative binomial probability of 'n' trials, with 'p' probability and 'r' as the successful outcome of each trial. I have written the following code that works sometimes, but not always:
Console.WriteLine ();
Console.WriteLine ("B~(n, p)");
incorrectN:
Console.WriteLine ("Enter value of 'n': ");
int n = Convert.ToInt32 (Console.ReadLine ());
if (n < 0) {
Console.WriteLine ("ERROR: 'n' must be greater than 0");
goto incorrectN;
}
incorrectP:
Console.WriteLine ();
Console.WriteLine ("Enter value of 'p': ");
double p = Convert.ToDouble (Console.ReadLine ());
if (p > 1) {
Console.WriteLine ();
Console.WriteLine ("ERROR: 'p' must be between 0 and 1");
goto incorrectP;
}
Console.WriteLine ();
incorrectS:
int r = GetR();
int k = r;
double binomTotal = 0;
for (int j = r + 1; j > 0; j--) {
int nCr = Factorial(n) / (Factorial(n - (r - k)) * Factorial(r - k));
binomTotal = binomTotal + nCr * Math.Pow(p, (r - k)) * Math.Pow(1 - p, (n - (r - k)));
k--;
}
Console.WriteLine();
Console.WriteLine(binomTotal);
P.S. I have written the GetR() and Factorial() functions elsewhere within the class, where GetR() asks the user for the value of 'r' and Factorial() is defined as follows:
public static int Factorial(int x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
I tested the code with values n = 10, p = 0.5 and r = 5 and the output is 0.623046875, which is correct. However, when I use n = 13, p = 0.35 and r = 7, I get 0.297403640622647 instead of 0.9538.
Any help would be much appreciated.
In addition to your own answer:
public static double Factorial(double x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
accepts a double parameter, which means that x is not restricted to be an integer.
So you could call your Factorial method like this.
var fac1 = Factorial(1.4);
var fac2 = Factorial(2.7);
However, this does not make sense since the factorial is defined only* for , meaning that
is undefined.
So, instead of using double and allowing for invalid inputs, you should be using long instead, which has a greater range than int.
public static long Factorial(long x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
* there are some cases where factorials can be used with real values as well - e.g. by using the gamma function - but I don't think they're relevant to your use case and therefore you should not allow invalid parameters.
Change:
public static int Factorial(int x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
To:
public static double Factorial(double x)
{
return x <= 1 ? 1 : x * Factorial(x - 1);
}
Because Factorial(13) is too large for Int32.
Related
I was working on this problem 278 First Bad Version on LeetCode. I have used binary search to get the element.
My way of getting middle index of an array m = (start + end)/2 was causing issue in case of large array, closer to MAX_LIMIT of int. First, I thought of int range overflow issue but I am not sure because it worked with end = MAX_LIMIT and some start < MAX_LIMIT even though its going over int range.
I would like to understand how m = start + (end - start)/2 is better than m = (start + end)/2
Code 1 works with input :
2147483647
98765432
But Code 1 fails with input:
2147483647
987654321
I think overflow issue should either happen in both cases or none of them.
1. Code which Worked with m = (start + end)/2 but fails for large array
public int FirstBadVersion(int n) {
if(n == 1){
return 1;
}
int s = 1;
int e = n;
int x = 0;
while(s != e){
x = (s+e)/2;
if(IsBadVersion(x)){
e = x;
}
else{
s = x + 1;
}
}
return s;
}
2. Code which worked with m = start + (end - start)/2
public int FirstBadVersion(int n) {
if(n == 1){
return 1;
}
int s = 1;
int e = n;
int x= 0;
while(s != e){
// x = (s+e)/2;
x = s + (e-s)/2;
if(IsBadVersion(x)){
e = x;
}
else{
s = x + 1;
}
}
return e;
}
You have integer overflow when computing
(a + b) / 2
when (a + b) > int.MaxValue the sum of (a + b) can't be represented as 32 bit integer (it requires 33 bits), and you have incorrect (often negative) result (when bit 33 is ignored) which you then divide by 2.
I suggest working with long in order to be safe from integer overflow:
public int FirstBadVersion(int n) {
// Special case: all versions starting from #1 failed
if (IsBadVersion(1))
return 1;
// let use long in order to avoid integer overflow
long correct = 1;
long failed = n;
// while we have unknown version between correct and failed
while (failed - correct > 1) {
int middle = (low + high) / 2); // it safe now : adding two long values
if (IsBadVersion(middle))
failed = middle;
else
correct = middle;
}
return (int)failed;
}
If using long is cheating and you want to stick to int, you can use the formula below, for int a, b we can put (note that we don't add big values a and b but their halves)
(a + b) / 2 == a / 2 + b / 2 + (a % 2 + b % 2) / 2
Please, note that your formula is not universal
(a + b) = a + (b - a) / 2;
it will work in the particular case of problem #278 where a and b are positive, but will fail in general casw, say when a = 1_000_000_000, b = -2_000_000_000.
How would I modify this for-loop so that it counts up for positive values of Step, but counts down for negative values of Step?
For Step = 2, the expected output is 2 4 6 8 10
For Step =- 2, the expected output is 10 8 6 4 2
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = 2;
for ( int i = Lower; i <= Upper; i += Step )
{
Console.Write(i + " ");
}
Just obey the KISS principle.
You can just put the logic into the initialiser and the condition of the for statement:
public static void ForLoopWithDirectionBasedOnStep(int minValue, int maxValue, int step)
{
// Avoid obvious hang
if ( step == 0 )
throw new ArgumentException("step cannot be zero");
// ( initialiser ; condition ; iterator )
for ( int i = step > 0 ? minValue : maxValue; minValue <= i && i <= maxValue; i += step )
Console.Write(i + " ");
}
so:
ForLoopWithDirectionBasedOnStep(minValue: 2, maxValue: 10, step: 2) returns:
2 4 6 8 10
ForLoopWithDirectionBasedOnStep(minValue: 2, maxValue: 10, step: -2) returns:
10 8 6 4 2
as desired.
The initialiser sets the start value
int i = step > 0 ? minValue : maxValue;
by using the conditional operator and is equivalent to
int i;
if ( step > 0 )
i = minValue;
else
i = maxValue;
The condition
minValue <= i && i <= maxValue
simply checks that the loop variable is within the range [minValue, maxValue].
Note that bad inputs are handled automatically because (emphasis mine):
The condition section, if present, must be a boolean expression. That expression is evaluated before every loop iteration.
so something like ForLoopWithDirectionBasedOnStep(minValue: 10, maxValue: 0, step: -2) which would count down from 0 to 10 doesn't print anything because, since 0 < 10, the body of the for statement is never executed.
You need a pre-processing step to change the comparison in the for loop as well as its limits
int Lower = 2;
int Upper = 10;
int Step = -2;
Func<int, bool> comparator = (j) => j <= Upper;
if (Step < 0)
{
var temp = Lower;
Lower = Upper;
Upper = temp;
comparator = (j) => j >= Upper;
}
for(int i=Lower; comparator(i); i+=Step)
{
Console.Write(i + " ");
}
DotNetFiddle
You can do two for loops based on the sign of the step variable:
static void Main(string[] args)
{
int lower = 2;
int upper = 10;
int step = -2;
if (Math.Sign(step) == 1)
{
for (int i = step; i < upper; i += step)
{
Console.WriteLine(string.Format("{0}", i));
}
}
else if (Math.Sign(step) == -1)
{
for (int i = upper; i >= lower; i += step)
{
Console.WriteLine(string.Format("{0}", i));
}
}
Console.ReadLine();
}
}
Note that this code is untested but the idea is to use a Predicate<T> for the loop and switching Upper and Lower if step is negative
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = 2;
if(step < 0){ int temp = Lower; Lower = Upper; Upper = temp;}
Predicate<int> LoopPred = (i =>
{
if(Step < 0)
return i >= Upper;
return i <= Upper;
})
for(int i=Lower; LoopPred(i); i+=Step)
{
Console.Write(i + “ “);
}
You can make a Func delegate to check if the step is negative and invert the bound checking condition.
Here's a sample:
class Program
{
public static void Print(int Lower, int Upper, int Step)
{
Func<int, bool> checkBounds = (i) => i <= Upper;
if (Step < 0)
{
Swap(ref Lower, ref Upper);
checkBounds = (i) => i >= Upper;
}
for (int i = Lower; checkBounds(i); i += Step)
Console.Write($"{i} ");
}
public static void Swap<T>(ref T a, ref T b)
{
T temp = a;
a = b;
b = temp;
}
static void Main(string[] args)
{
// assume these 3 come from user input
int Lower = 2;
int Upper = 10;
int Step = -2;
Print(Lower, Upper, Step);
}
}
for(int i=Step>0?Lower:Upper; Step>0? i<=Upper: i>= Lower; i+=Step)
{
Console.Write(i + " ");
}
#john All you need to update the looping conditions.
static void Main(string[] args)
{
Console.WriteLine("Enter your number: ");
int number= Convert.ToInt32(Console.ReadLine());
int number2 = Convert.ToInt32(Console.ReadLine());
double factorial = Factorial(number,number2);
Console.WriteLine("Factorial of " + number +" / "+ number2 + " = " + factorial );
Console.ReadKey();
}
//Factorial function added
public static double Factorial(int number, int number2)
{
if (number == 1 && number2 ==1 )
{
return 1;
}
double factorial = 1;
double factorial1 = 1;
double factorial2 = 1;
for (int i = number, j = number2; i >= 1 && j >= 1; i--, j--)
{
factorial1 = (factorial * i);
factorial2 = (factorial * j);
factorial = factorial1 / factorial2;
}
return factorial;
}
Your attempted solution is simply so overcomplicated, I wouldn't know where to begin. This usually happens when you don't stop to think about how you'd resolve this problem by hand:
So, the question is, whats 5!/3!? Ok, lets write it out:
(5 * 4 * 3 * 2 * 1) / (3 * 2 * 1)
Wow, that looks like it can be simplified simply to 5 * 4.
The key insight here is that m! % n! = 0 if n is less or equal to m. In other words, m! is always divisible by n! because there is always an integer r such that r * n! = m!, and you don't need to evaluate m! or n! to figure out what r is, you simple do:
r = m * (m - 1) * (m - 2) * ... * (n + 1); // m >= n
If n > m, r is zero unless you are looking for a real number solution in which case you would simply evaluate r as n! / m! and then return 1.0 / r because m! / n! = 1 / (n! / m!).
How to evaluate r?
public static long DivideFactorials(int m, int n)
{
if (n > m)
return 0;
var r = 1L;
for (var k = m; k > n; k--)
r *= k;
return r;
}
Or the real number solution:
public static double DivideFactorials(int m, int n)
{
if (n > m)
return 1 / DivideFactorials(n, m);
var r = 1.0;
for (var k = m; k > n; k--)
r *= k;
return r;
}
If I had to save your try:
public static double Factorial(int number, int number2)
{
if (number == 1 && number2 == 1)
{
return 1;
}
double facNum = 1;
double facNum2 = 1;
// counting up is easier, we start at 2 as we initialized to 1
// we count up to the max of both numbers
for (int i = 2; i <= Math.Max(number, number2); i++)
{
if (i <= number)
facNum *= i; // we mult this until we reached number
if (i <= number2)
facNum2 *= i; // we mult this until we reach number2
}
// return the devision of both - this wont handle number < number2 well!
return facNum / facNum2; // do this outside the loop
}
If I had to create a solution:
Factorial division of integers has 3 outcomes (I can think of):
N! / O! with N == O:
let N=3, O=3
N! = 1*2*3
O! = 1*2*3
N! / O! = 1*2*3/(1*2*3) == 1
N! / O! with N > O:
let N=5, O=3
N! = 1*2*3*4*5
O! = 1*2*3
N! / O! == 1*2*3*4*5/(1*2*3) == 4*5 == 20
N! / O! with N < O:
let N=3, O=5
N! = 1*2*3
O! = 1*2*3*4*5
N! / O! == 1*2*3/(1*2*3*4*5) == 1/(4*5) == 1/20
Based on this I would model the problem like that:
using System;
using System.Collections.Generic;
using System.Linq;
internal class Program
{
public static decimal CalcFactDivision(int n1, int n2)
{
// calclulate the division of a factorial by another, num1 must be >= num2
IEnumerable<int> getRemaining(int num1, int num2)
{
// special cases: div by 0 and 0 div something
if (num2 == 0)
num2 = 1; // 0! == 1
else if (num1 == 0)
return new[] { 0 };
// get all numbers that make up the factorial in one step
// I can guarantee that num1 will always be bigger then num2
// by how I call this
return Enumerable.Range(num2 + 1, num1 - num2);
}
// calculate the product of an ienumerable of ints
int product(IEnumerable<int> nums) => nums.Aggregate((a, b) => a * b);
if (n1 == n2)
return 1;
else if (n1 > n2) // use product(...) to calc
return product(getRemaining(n1, n2));
else // flip them and use 1/product(...) to calc
return (decimal)1 / product(getRemaining(n2, n1));
}
static void Main(string[] args)
{
foreach (var a in Enumerable.Range(1, 10))
Console.WriteLine($"{a}! / {10 - a}! = {CalcFactDivision(a, 10 - a)} ");
Console.ReadLine();
}
}
Output:
1! / 9! = 0,0000027557319223985890652557
2! / 8! = 0,0000496031746031746031746032
3! / 7! = 0,0011904761904761904761904762
4! / 6! = 0,0333333333333333333333333333
5! / 5! = 1
6! / 4! = 30
7! / 3! = 840
8! / 2! = 20160
9! / 1! = 362880
10! / 0! = 3628800
int y = 0;
Console.WriteLine("insert x");
int x = Console.Read();
Console.WriteLine("insert n");
int n = Console.Read();
Console.WriteLine("insert a");
int a = Console.Read();
int sum = (2 * n - 1) * a;
int sum2 = (2 * n * a);
int sum3 = (2 * n + 1) * a;
if (x <= 0) y = 0;
else if (x > sum && x <= sum2) y = a;
else if (x > sum2 && x <= sum3 || n <= 3 || n >= 1) y = 0;
Console.WriteLine("Y = " + y);
Console.ReadLine();
}
can't insert all values. after i insert x y printed and console close, what is my mistake?
Instead of Read use ReadLine. Only then you can be sure the user actually pressed ENTER and the entire line is returned - Read blocks until the user presses ENTER, but then returns the ASCII code of only one character. If you read the documentation example, this becomes clear.
In your example, if you enter "1" and press ENTER, the next calls to Read will actually return the ASCII codes for 1, \r and \n.
To be clear: Read does not return the entered number, but the ASCII code of the character you entered, so you're using it wrong - what you need to do is convert the string the user enters to a number like so:
int number = Convert.ToInt32(Console.ReadLine());
You could also check for errors easily like this:
int number;
if (!Int32.TryParse(Console.ReadLine(), out number))
{
Console.WriteLine("What you entered is not a number!");
return;
}
The Console.Read reads only the next character. This is not what you want. What happens is this:
you type 7 => you read the character (ascii code) 0x37 for x
you press ENTER => you read 0x0A (\r) for n
etc...
you want to use Console.ReadLine() which terminates when you hit ENTER and returns a string that you can parse as int:
Console.Write("Insert x: ");
string input = Console.ReadLine();
int x = int.Parse(input);
You may want to add error handling if the user types "abc" instead of an int or use
int x;
if (!int.TryParse(input, out x))
Console.WriteLine("This was no number!");
You should use ReadLine and convert to int 32
Thes is the right code:
int y = 0;
Console.WriteLine("insert x");
int x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("insert n");
int n = Convert.ToInt32(Console.ReadLine());
Console.WriteLine("insert a");
int a = Convert.ToInt32(Console.ReadLine());
int sum = (2 * n - 1) * a;
int sum2 = (2 * n * a);
int sum3 = (2 * n + 1) * a;
if (x <= 0) y = 0;
else if (x > sum && x <= sum2) y = a;
else if (x > sum2 && x <= sum3 || n <= 3 || n >= 1) y = 0;
Console.WriteLine("Y = " + y);
Console.ReadLine();
Everyone has given a solution but the reason why
Your code doesn't work is this.
The
Console.Read
Returns the ASCII value of the keypressed.
It means saying something like
int i = Console.Read();
And hitting the 4key on your keyboard will store the value 53, which is the ASCII value of the 4key in variable i instead of ur intended integer "4".
To fully understand this check variable values by using breakpoints after Console.Read to see what is really stored in variable a, n and y.
I'm trying to implement the recursive definition for B-Splines in c# but I can't get it right. Here's what I've done:
public static Double RecursiveBSpline(int i, Double[] t, int order, Double x)
{
Double result = 0;
if (order == 0)
{
if (t[i] <= x && x < t[i + 1])
{
result = 1;
}
else
{
result = 0;
}
}
else
{
Double denom1, denom2, num1, num2;
denom1 = t[i + order + 1] - t[i + 1];
denom2 = t[i + order] - t[i];
if (denom1 == 0)
{
num1 = 0;
}
else
{
num1 = t[i + order + 1] - x / denom1;
}
if (denom2 == 0)
{
num2 = 0;
}
else
{
num2 = x - t[i] / denom2;
}
result = num1 * RecursiveBSpline(i + 1, t, order - 1, x)
+ num2 * RecursiveBSpline(i, t, order - 1, x);
}
return result;
}
And here is how I call the function:
Double[] vect = new Double[] { 0, 1, 2, 3 };
MessageBox.Show(BSpline.RecursiveBSpline(0,vect,2,0.5).ToString());
I should see 0,125 on the screen, instead I get 0,25. The two denominator variables are used to check if they equal 0 and if they do, the number should be set to 0 by definition. Can someone point out where I'm getting this wrong?
Bear in mind, that the mathematical and logical operators in C# have a precedence order. Your second solution works fine if you put the right terms in braces (explanation follows). This line:
num2 = x - t[i] / denom2;
should be changed to:
num2 = (x - t[i]) / denom2;
and so on. Then the result is as desired: 0.125
The division operator has a higher order precedence as the addition operator. To affect the execution order use braces (everything in braces will be evaluated at first):
var r1 = 2 + 2 / 2; // Step1: 2 / 2 = 1 Step2: 2 + 1 Output: 3
var r2 = (2 + 2) / 2; // Step1: (2 + 2) = 4 Step2: 4 / 2 = 2 Output: 2