Can't understand the code snippet - c#

I am doing some basic C# exercises to learn C#.The website provides the solutions to the problems too however, I am unable to understand the code.
Problem:
Write a C# program to check if an integer is within 20 of 100 or 200.
Sample Output:
Input an integer
25
False
Solution:
public class Exercise22
{
static void Main(string[] args)
{
Console.WriteLine("\nInput an integer:");
int x = Convert.ToInt32(Console.ReadLine());
Console.WriteLine(result(x));
}
public static bool result(int n)
{
//Can't understand the code below -
//why is the "<=10" and "return false" used
if (Math.Abs(n - 100) <= 10 || Math.Abs(n - 200) <= 10)
return true;
return false;
}
}

Math.Abs() gives you the absolute value of the argument.
If n is between 90 and 110 (within 20 around 100), then n-100 is between -10 and 10, so Math.Abs() will return a value between 0 and 10.
The same is done for 200.
You could however simplify this to:
return Math.Abs(n-100) <= 10 || Math.Abs(n-200) <= 10;
So if n is in one of the ranges, true is returned and the function ends.
Otherwise, the function skips the return true and continues to return false.

if is obviously a condition, following statements are only executed when the condition passes. In your case execution will leave the method by executing return true.
I assume you think you´d need an else to indicate what happens when the condition does not pass. Usually this is right. However in this special case there´s no way to reach the return false-statement when the if passes, as in this case (as described earlier) the method will terminate.
So you could also write this, which is completely identical:
if (Math.Abs(n - 100) <= 10 || Math.Abs(n - 200) <= 10)
return true;
else
return false;
So all in all there´s no other way that the return false-statement is executed than the condition evaluating to false.

Related

C#: Random.NextDouble method stalling out application

I'm receiving some inconsistent behavior from the Random.NextDouble().
Regularly, the console would freeze and the cpu usage would increase dramatically until I closed it down. I ran the debugger and found that the cause of the freezing was Random.NextDouble(). I added some lines for debugging purposes, but the code is as follows:
double generateCatenationRate()
{
double catenation = 999.999; //random value to see if it pops up down there
double uniformValue;
double int_covalence = covalence.original;
double dist = int_covalence - 4;
int counter = 0;
while (true)
{
counter++;
uniformValue = utils.getRandomDouble(); //goes bad here!
if (uniformValue <= 0.15)
{
catenation = Math.Abs(utils.normalize(dist, 0, 4)) + uniformValue;
if (catenation < 0 || catenation > 1)
{
if (counter > 10000)
{
Console.WriteLine("Went nuclear!");
break; //break so console doesn't stall out
}
continue;
}
else
{
break;
}
}
}
Console.WriteLine("Took "+counter+" iterations.");
return 1 - catenation;
}
And:
public static double getRandomDouble()
{
Init();
return random.NextDouble();
}
Lastly:
private static void Init()
{
if (random == null) random = new Random();
}
It typically does not stall out, but running it several times successively produces output such as:
Took 4 iterations.
Took 3 iterations
Took 3 iterations.
Took 23 iterations.
Took 12 iterations.
Took 4 iterations.
Went nuclear!
Took 10007 iterations.
Can anyone explain why Random.NextDouble() occasionally seems to create an infinite loop? Looking around, I suspect it has something to do with how the values are seeded, but any insight would be appreciated; would love to fix this issue.
Thank you!
EDIT: covalence.original is always an integer between 1 and 8 (inclusive). normalize() performs min-max normalization, producing a number from 0-1 based on an input and a range. Neither of these seem to contribute to the problem, however.
If I understand correctly then the value of dist and utils.normalize(dist, 0, 4) never changes.
So if int_covalence = 8 then dist = 4 and utils.normalize(dist, 0, 4) = 1, correct?
Since the chance of generating 0.0 is pretty small, that will make catenation virtually always greater than 1 and the check if (catenation < 0 || catenation > 1) always true.
why not just generate the samples directly rather than using rejection sampling?
public static double generateCatenationRate(Random rng, double coval_norm) {
double low = Math.abs(coval_norm) + 0.15;
double delta = 1. - low;
if (delta < 0) {
throw new IllegalArgumentException("impossible given covalence");
}
return low + delta * rng.nextDouble();
}
where coval_norm is whatever you get back from utils.normalize. if we write it this way we get visibility of the "impossible" condition and can do something about it, rather than just looping.

Test a subtraction and apply it if the result is greater than zero

I'm minimalist and I want that my code has as less lines as possible. In every code I write, my goal is to use as much one-lined instructions as possible and avoiding any recurrent code.
Today I'm facing a problem, I'm not able to reduce an instruction even if I'm convinced it's possible.Let's have a look at my instruction :
if((level - 2) >= 0)
{
level -= 2;
}
If know I can use a one-lined affectation in the if like that :
if((level -= 2) >= 0)
But the subtraction while be always applied even if the test is false.
How can I compact this instruction in one line ?
EDIT
I can't use ternary operator because I have to keep the if instruction. Basically I have to execute several operations if the test is true, I just simplified my code to post it.
You could use the ternary operator like this
level -= level - 2 >= 0 ? 2 : 0;
or simpler
level -= level >= 2 ? 2 : 0;
But I don't think that making everything as "short " as possible is the right way to go.
Only subtract when the level is larger or equal to the value you would subtract.
if(level >= 2)
{
level -= 2;
}
Write a general function:
public static bool TryToSubtract(ref int from, int value)
{
bool result = false;
if (from >= value)
{
from -= value;
result = true;
}
return result;
}
and then use that
TryToSubtract(ref level, 2);
You can then even make further statements based on the outcome:
if(TryToSubtract(ref level, 2))
{
Console.WriteLine("Your level was reduced!");
Console.WriteLine("You loser!");
}
If you can live without curlies and newlines, then this could be the shortest, and still very readable (IMHO):
if (level >= 2) level -= 2;

unity library function always returning 0

I have written a library for unity and one function is supposed to return time played. might be easier to explain with the code.
public int UNI_TimePlayed(int timePlayed)
{
if (timePlayed != 60)
{
// division impossible, treat this exception here
return timePlayed;
}
else
{
// it's safe to divide
int timeInMin = timePlayed / 60;
return timeInMin;
}
}
if the time played is not equal to 60 seconds then it should return the value. if it is 60 or over then carry out the equation and return the new value.
when I call this in unity, it will only work once my timer goes over 60 seconds, if not then it returns 0., for example, my timer in unity works, I log the value from it before it is inserted into this function. on one occasion the value inserted was 62, the function returned a correct value to me. this occasion the timer was 23 and when this was inserted the function returned 0? as you can see I have tried to get it to just return the value inserted if it is less than 60 but it will not work.
You used != which means "not equal". You should use < which means "less than".
public int UNI_TimePlayed(int timePlayed)
{
if (timePlayed < 60) return timePlayed;
return timePlayed / 60;
}
However, a value suddenly changing from seconds to minutes is quite surprising. Returning a string containing the unit would seem more natural.
public string UNI_TimePlayed(int timePlayed)
{
if (timePlayed < 60) return $"{timePlayed} s";
return $"{timePlayed / 60} min";
}

Strange values in a recursion method in C#

As an exercise, One of our student in apprenticeship is supposed to implement a recursive Sine function. (Using the generalized continued fraction)
I tried to help him, having done a fair share of coding in comparison, and am now stuck with a problem I don't understand.
I have a function that works.
What I don't understand is why my first three or four attempt failed.
I tried to debug this thing step-by-step but I can't pinpoint my error. I really would like to know what I'm missing.
Beware, for the code is not as beautiful as it could be. It's a quick and dirty proof of concept I wrote (many times) in 5 minutes.
Here's the code that doesn't work:
// number = the angle in radian
static double sinus(double number, double exp = 1, bool mustAdd = false, double precision = 0.000001)
{
if (number < 0) throw new ArgumentException("sinus");
if (number == 0) return 0;
double result = ((Math.Pow(number, exp)) / factorial(exp));
Console.WriteLine(result);
if (result > precision)
{
if (mustAdd)
return result += sinus(number, exp + 2, !mustAdd);
else
return result -= sinus(number, exp + 2, !mustAdd);
}
else
return result;
}
I'm printing every iteration with the intermediate values, in order to verify that everything is working accordingly. The values are correct.
Here's the working code I came up with (Yes it's dirty too):
static double Altersinus(double number, double exp = 1, bool mustAdd = true, double precision = 0.000001, double result = 0)
{
if (number < 0) throw new ArgumentException("altersinus");
if (number == 0) return 0;
double tmp = ((Math.Pow(number, exp)) / factorial(exp));
Console.WriteLine(tmp);
if (tmp > precision)
{
if (mustAdd)
result += tmp;
else
result -= tmp;
result = Altersinus(number, exp + 2, !mustAdd, precision, result);
}
return result;
}
I'm also writing the intermediate values, and they are exactly the same as the function that doesn't work.
Again, I'm really not searching for a solution, there is no rush. I'm merely trying to understand why it's not working. I would like to know what's technically different between my two methods.
Any idea would be much appreciated.
Cheers.
EDIT
I tried both function with the value 3.14159265358979 (roughly 180 degree)
Both function are printing theses intermediate values :
3.14159265358979
5.16771278004997
2.55016403987735
0.599264529320792
0.0821458866111282
0.00737043094571435
0.000466302805767612
2.19153534478302E-05
7.95205400147551E-07
The method that doesn't works returns -3.90268777359824 as a result, which is completely false.
The one that does works returns -7.72785889430639E-07. Which roughly corresponds to a zero.
I figured it out.
Let's replace the calculus by 'nx' where x is the exposant and n the number.
In the function that does work, I am effectively this:
Sine(n)=n1/1! - n3/3! + n5/5! - nx/x!...
But the one that doesn't work is slightly different. It's doing something else:
Sine(n)=n1/1! - (n3/3! + (n5/5! - (nx/x!...)))
The key here are the parenthesis.
It's affecting the calculus big time, because of the substraction.
If there was only addition it would not have caused any problem.

Project Euler 10: simple code is not giving the desired result, need help understanding why

I'm solving Project Euler problems for kicks, I'm currently at number 10.
First of all: I know there are other solutions, I'm currently writing another method using the sieve of Eratosthenes. What I'd like your help with is understanding why this code does not work.
This is my code (the problems involves finding the sum of every prime under 2 million). The prime-checking method seems to work fine, but the result is way less than it should be.
class Euler10
{
public static void Main()
{
long sum = 0; // Was originally an int. Thanks Soner Gönül!
for(int i = 1; i < 2000000; i++)
{
if (CheckIfPrime(i) == true)
sum += i;
}
System.Console.WriteLine(sum);
System.Console.Read();
}
static bool CheckIfPrime(int number)
{
if (number <= 1)
return false;
if (number == 2)
return true;
if (number % 2 == 0)
return false;
for (int i = 3; i*i < number; i += 2)
{
if ((number % i) == 0)
return false;
}
return true;
}
}
The number I get is 1,308,111,344, which is two orders of magnitude lower than it should be. The code is so simple I am baffled by this error.
EDIT: making sum a long solved the digit problem, thanks everyone! Now, though, I get 143042032112 as an answer: the i*i in CheckIfPrime() isn't always right.
Using the sqrt() function and adding one (to compensate for the int cast) gives the correct result. Here's the correct CheckIfPrime() function:
bool CheckIfPrime(int number)
{
if (number <= 1)
return false;
if (number == 2)
return true;
if (number % 2 == 0)
return false;
int max = 1 + (int)System.Math.Sqrt(number);
for (int i = 3; i < max; i += 2)
{
if ((number % i) == 0)
return false;
}
return true;
}
EDIT 2: Will Ness helped me optimize the code further (calculating number's square root and comparing it to i is slower than elevating i^2 and then comparing it to number): the problem with the original method is that it didn't take into consideration edge cases in which number is the exact square of i, thus sometimes returning true instead of false. The correct code for CheckIfPrime(), then, is:
bool CheckIfPrime(int number)
{
if (number <= 1)
return false;
if (number == 2)
return true;
if (number % 2 == 0)
return false;
for (int i = 3; i*i <= number; i += 2)
{
if ((number % i) == 0)
return false;
}
return true;
}
Thanks again people!
Your code does not work because it tries using a 32-bit int to hold a number that exceeds the highest value in a 32-bit variable. The answer to the problem is 142,913,828,922, which needs 38 bits.
Changing the data type of sum to long should fix this problem.
Using long should help.http://msdn.microsoft.com/en-us/library/ctetwysk.aspx
Gives you a 64 bit integer where as int is only 32 bits.
You are using int for sum variable which is 32-bit but you are try to assign it more than Int32.Maximum which is 2,147,483,647.
But your result is 143,042,032,112 which needs more bits than 32 for storing it.
Set its type as long which stores 64 bit.
long sum = 0;
Here a working DEMO.
for (... i=3 ; i*i < number; i+=2 ) is wrong. It should be
for (... i=3 ; i*i <= number; i+=2 )
...
both i and number must be of the same type of course; this will almost never give you an overflow, since you start from 3 (unless number is very big, close to the upper limit of the type's range).
The comparison should be inclusive to catch cases where number is a square of a prime.
Your algorithm is not the Sieve of Eratosthenes; the modulo operator gives it away. Your algorithm is trial division by odd numbers. Here is a function using the Sieve of Eratosthenes:
function sumPrimes(n)
sum := 0
sieve := makeArray(2..n, True)
for p from 2 to n step 1
if sieve[p]
sum := sum + p
for i from p * p to n step p
sieve[i] := False
return sum
Calling sumPrimes(2000000) gives the answer, which I won't write down out of respect for Project Euler. That function runs in time O(n log log n), which is much better than the O(n^2) of your original program. There are better ways to sieve, but that is simple, and easy to get right, and good enough for most purposes, including yours. You should get an answer in less than a second.
I'll leave it to you to translate to C# with appropriate data types.
If you're interested in a somewhat larger version of this problem, I calculated the sum of the first billion primes at my blog: 11138479445180240497.

Categories

Resources