unity library function always returning 0 - c#

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";
}

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.

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.

Can't understand the code snippet

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.

Creating random data C#

I'm trying to create a heart beat monitor and need some false information to feed into my program to check it works.
One of the requirements of my program is to set off an alarm if the heart rate integer drops below a certain figure.
However the problem I have is, if the heart rate drops below the minimum heart rate integer before it sets off the alarm and then bounces straight back up again, that's not a test for the alarm, see pseudo code:
If heart_rate < 60:
Count = Count + 1
If heart _rate > 60:
Reset Count variable
If Count = 10:
Set off alarm
So I need to generate data where it simulates a heart rate dropping below 60 (patient dieing).
Would the quickest way to do this create a list or text file that the program reads from to simulate the situation or is there a funky way that can simulate random numbers that can set off the alarm and will stay around that integer once the alarm has been set off?
Sorry if this sounds super confusing, I'm a python programmer, having to program in C#.
Your problem seams to be a "data stream testing" one. Manually generating data streams is not something I would personally characterize as "quick" (or even "sane"...). You either get an existing data set or you generate it (but not manually, unless it's a relatively small number of data points: 20~30).
That being said, you need to test something, which means you need to know that when a target case (heart rate below 60), your system correctly catches the "exception". This, in turn, means that you need to know where it happens, i.e. the exact moment in time.
My advice is: automatically generate a data set, full of "normal" values. At different time point (i.e. position in the data stream) manually insert "exception" values (59), with different frequencies, to see if the system resets the counter (less than 10 occurrences) or if it raises an alarm (at least 10 occurrences).
You would then have the following initial data stream:
80 78 78 81 80 81 ... 75 76 80 // say 100 values ("data points")
// 0 1 2 3 4 5 97 98 99 -> indices ("time points")
If you insert a "false alarm" (80 78 59 59 78) at index 2, for example, you know that your system should reset the counter. You would do the same for the "alarm"; you'll know the index (time point) when the alarm should be raised.
Edit: the part about "manually" inserting the targeted values should be interpreted as "empirically selecting an index of an array (or a list) filled with random data, where the data should be inserted".
public static class HeartrateGenerator
{
static Random random = new Random();
public static IEnumerable<int> GenerateHeartrate(
int totalSequenceLength,
int dropsBelow60After,
int bouncesBackAfter = -1)
{
// NOTE: check input data
int i = 0;
// return values > 60
while (i < dropsBelow60After)
{
i++;
yield return 60 + random.Next() % 60;
}
if (bouncesBackAfter > 0)
// return values < 60
while (i < bouncesBackAfter)
{
i++;
yield return random.Next() % 60;
}
// return normal values again
while (i < totalSequenceLength)
{
i++;
yield return 60 + random.Next() % 60;
}
}
}
example usage:
HeartrateGenerator.GenerateHeartrate(100, 20, 28);
Try this: you might want to change the rand.Next(min,max) to use normal range of heartbeat or whatever range you want to see for a heartbeat value.
public class Program
{
public void Main(string[] args)
{
Random rand = new Random();
bool flag = true;
int count = 0;
while (flag)
{
if(count==10)
{
Console.WriteLine ("dead");
flag = false;
break;
}
Thread.Sleep(1000);
var heart_rate = rand.Next(50,70);
Console.WriteLine (heart_rate);
if (heart_rate < 60)
{
count++;
}
else if(heart_rate > 60)
{
count=0;
}
}
}
}

Efficient Level up after every 10?

I'm trying to make it so that after every say 200 of a value, it will increase a global variable by 1. As you can see below the problem I have is that one, it isn't in any way shape or form efficient and really doesn't work well.
An overall of how I'd like this to work would be so that when GV.TotalNumberValue hits past a certain number, let's say 200, GV.TotalLevel will increase by one and update the text and this will happen every time that GV.TotalNumberValue increases by 200.
Finally, if this is going to be checking what the number is on constantly, should I have this bound to an event such as a button click or a timer? Your help's greatly appreciated, thanks.
void LevelMod()
{
if (GV.TotalNumberValue >= 200)
{
GV.TotalLevel = GV.TotalLevel + 1;
lblLevel.Text = string.Format("{0}{1}", GV.LevelPrefix, GV.TotalLevel);
}
else if (GV.TotalNumberValue >= 400)
{
GV.TotalLevel = GV.TotalLevel + 1;
lblLevel.Text = string.Format("{0}{1}", GV.LevelPrefix, GV.TotalLevel);
}
else
{
return;
}
}
Well, you can use simple math:
Either deduce the level from the value, like this:
int totalLevel = value / 200;
This works because an integer division is always rounded down.
Or, if you know that value has just been incremented, you can detect a level boundary like this:
bool shouldLevelUp = (value % 200) == 0;
if (shouldLevelUp)
++totalLevel;
Perhaps use integer division similar to:
void LevelMod()
{
// I assume the level variables are integrals, so perform an integer division
if (GV.TotalNumberValue / 200 > GV.TotalLevel)
{
GV.TotalLevel = GV.TotalNumberValue / 200;
lblLevel.Text = string.Format("{0}{1}", GV.LevelPrefix, GV.TotalLevel);
}
}
Essentially, your TotalLevel is always TotalNumberValue / 200. This assumes that that GV.TotalNumberValue is an integral type which always rounds the result towards zero.

Categories

Resources