How do i convert Floor in excel to Unity Mathf? - c#

How do i convert Floor in excel to Unity Mathf? I have a procedural equations like this in Excel:
= FLOOR(MOD(5, 20) * 0.2, 1)
and i want to convert it to C# Script but i can't. I have already tried:
float test = Mathf.Floor((5 % 20) * (1 / 5));
But it's not what i want. The answer that i want is 1 (Like the result from Excel) but in C# Script it is 0. Please give me some suggestions and thanks for that!

1 / 5
is an integer division with result 0! Therefore
Mathf.Floor((5 % 20) * 0);
is obviously also 0.
You should either use a float division by simply using a float value for at least one of the two operands
1f / 5f
or why not simply directly use the float value
0.2f
so your line should be
float test = Mathf.Floor(5 % 20 * 0.2f);
Note: If you would like to get the result directly as an int value you might want to use Mathf.FloorToInt instead.
Just for completeness: Excel's FLOOR has a second parameter significance
The multiple to which you want to round.
In order to also fake that in your line you would do
var result = Mathf.Floor(5 % 20 * 0.2f / significance) * significance;

Related

Math Operation in Windows Form Application [duplicate]

This question already has answers here:
Why does integer division in C# return an integer and not a float?
(8 answers)
Closed 1 year ago.
I am trying to use a function in windows form application that convert a given point to another coordinate system. However, I encountered a strange problem. The input are correct but output is always 0. First, I thought it caused because of the local variables and then instead of variables I used only integers but it did not solve. I have no idea about it. Here the code and output basically:
string[] newPoint1 = convertPoints(X1, Y1);
string[] convertPoints(int oldX, int oldY)
{
//int newX = ((oldX - oldLeft) / (oldRight - oldLeft)) * (newRight - newLeft);
MessageBox.Show(oldX.ToString()); // output is 296
int newX = (oldX / 500) * 4096; // ????????????????????? (296/500) * 4096 = 0 ?????????????
MessageBox.Show(newX.ToString()); // here output is 0
int newY = newTop + ((oldY - oldTop) / (oldBottom - oldTop)) * (newBottom - newTop);
//MessageBox.Show(newY.ToString());
string[] newPoints = {newX.ToString(), newY.ToString()};
//MessageBox.Show(newPoints[0], newPoints[1]);
return newPoints;
}
This is working as it should. Because oldX is an Integer, when you divide it, it rounds (drops anything after the decimal). I would convert it to float and back into an integer, like so
int newX = (int)(((float)oldX / 500) * 4096);
This will preserve the whole number until you're done at the end. You'll also need to do the same for the Y values
An integer division cuts off the decimal places. So in your case, 296/500 you would expect 0.592. As integer has no decimal places, it cuts off them off resulting in 0.
Change the oldX to double and divide by 500.0
You are getting 0 because oldX/500 is a fraction usually and since you are using the int datatypes there can only be whole numbers. What I would recommend doing is changing the data type then rounding yourself.
//Old code
int newX = (1 / 500);
Console.WriteLine(newX);
// writes 0 to console
//New code
double newXD = (1 / 500.0) * 4096;
Console.WriteLine(newXD);
//Writes 8.192
The 1 and the 500 are considered ints try
Console.WriteLine(1/500);
It writes 0 to the console.
Console.WriteLine(1/500.0);
Console.WriteLine((float)1/500);
Console.WriteLine((double)1/500);
All these write 8.192 to the console.
Then after you have the double or other more accurate data type consider rounding if you really want an int.

C# - Infinite numbers

I'm currently work on a certain program (in C# .NET - winforms), and among the things i came across the following problem:
I need to calculate the point (t, f(t)) given that:
f(t) = [Sin(t) / 16*Cos^4(t)]^(1/3), Such that: t: -89.995 -> 89.995. (t is real number).
Note: the value of t is ranges from -89.995 to 89.995.
I use the .NET functions Math.Sin(), Math.Cos(), Math.Pow() for the calculations, the converssions from radians to degrees are correct and all right.
The problem is that for every t < 0 that i put in f(t) i got NaN ( = not a number) from the above functions, and when i calculate it in a standard calculator i get standard correct values.
For examplae: t = -0.9165664, f(t) = -0.1000096, (Taht's the correct result).
but when i use the .NET functions in my program, the result i get for t = -0.9165664 is NaN (= Not a Number), why? it's not an exeption, not dividing by zero or something like that.
The code i use in the program:
float t = -0.9165664;
float numerator = Math.Sin(t * Math.PI / 180.0f);
float denominator = 16.0f * Math.Pow(Math.Cos(t * Math.PI / 180.0f), 4)
float ft = (float)Math.Pow(numerator / denominator, 1.0f / 3.0f));
Note: I can't cahnge the type of ft to double.
When i put any t > 0 in the above code it gives the correct result.
Can someone explain me what wrong or suggest a possible solution?
Thanks for help!!!
The problem is the definition of the Math.Pow function, see the documentation. Since your exponent is fixed and you're looking for the 3rd root as a real number, try something like
float t = -0.9165664;
float numerator = Math.Sin(t * Math.PI / 180.0f);
float denominator = 16.0f * Math.Pow(Math.Cos(t * Math.PI / 180.0f), 4)
float val = numerator / denominator;
float ft = Math.Sign(val) * (float)Math.Pow(Math.Abs(val), 1.0f / 3.0f));

percent calculation not working?

Its a very interesting thing not sure why it happens but when I do:
(item.Count / query.Count) * 100
It will not give me any errors just reply with 0 and when I do:
(item.Count * 100) / query.Count
It works just fine, what am I missing here ?
Another problem I am having is formatting the output of it to string:
double perc = (item.Count * 100) / query.Count;
MessageBox.Show(perc.ToString("P5"));
Does not work gives me a huge sum like 33,333.33 or 33,000.00, I wanted it to look like this 33.33%, I tried several variations but for some reason it will not let me get the .33 if I set the parenthesis to double it gets me .00 and if I do not it doesn't give me .33
Don't multiply by 100, the Percent Format Specifier will do that for you. Just cast to double when you perform the division:
double perc = (double)item.Count / (double)query.Count;
MessageBox.Show(perc.ToString("P5"));
(item.Count / query.Count) * 100
is doing integer division and thus (item.Count / query.Count) will always evaluate to zero. Casting as doubles prior to division will fix this.
For your formatting issue, try using String.format
ie. string result = string.Format("string = {0:0.0%}",
perc);
More string formatting methods can be found here: http://www.dotnetperls.com/string-format
try to do (item.Count * 100d) the "d" specified that the 100 is a double. going to return you a double and also when you going to divide by query.Count
100f for float hundred
item.Count and query.count are integers, cast them like (float)item.Count to convert them, otherwise it will do integer division and will always round down to 0.
((float)item.Count / (float)query.Count) * 100;
You are not casting (item.Count / query.Count) to a double before a division. So an int*double is 0 for some reason (at least in my code). Do ((double)item.Count / (double)query.Count) and either change 100 to 100.0 or change it to (double)100. However, the later I recommend as 100 is converted to a double at runtime instead of at compile time.
Change your 100 to 100.00. It needs to know it's not an int
Try:
double perc = ((double)item.Count * 100.00) / (double)query.Count;
MessageBox.Show(perc.ToString("P5"));

Why does (int)(float.Parse("0.04", System.Globalization.CultureInfo.InvariantCulture) * 100) equals 3

My boss reported my a bug today because my configuration was decreasing whenever he wanted to specify a value below 5%. I know that I can just round my number before casting it as int to fix my problem, but I don't understand why this problem occurs.
I have a app.config file with the value "0.04" and a configuration section with a float property. When the section is read, the float value retrieved is 0.04, which is fine. I want to put this value in a windows forms TrackBar which accept an integer value so I multiply my value by 100 and a cast it as int. For some reason, the result is not 4, but it's 3. You can test it like this :
Console.WriteLine((int)(float.Parse("0.04", System.Globalization.CultureInfo.InvariantCulture) * 100)); // 3
What happened?
It's because 0.04 can't be exactly represented as a float - and neither can the result of multiplying it by 100. The result is very slightly less than 4, so the cast to int truncates it.
Basically, if you want to use numbers represented accurately in decimal, you should use the decimal type instead of float or double. See my articles on decimal floating point and binary floating point for more information.
EDIT: There's something more interesting going on here, actually... in particular, if you assign the result to a local variable first, that changes the result:
using System;
using System.Globalization;
class Test
{
static void Main()
{
// Assign first, then multiply and assign back, then print
float f = Foo();
f *= 100;
Console.WriteLine((int) f); // Prints 4
// Assign once, then multiply within the expression...
f = Foo();
Console.WriteLine((int) (f * 100)); // Prints 4
Console.WriteLine((int) (Foo() * 100)); // Prints 3
}
// No need to do parsing here. We just need to get the results from a method
static float Foo()
{
return 0.04f;
}
}
I'm not sure exactly what's going on here, but the exact value of 0.04f is:
0.039999999105930328369140625
... so it does make sense for it not to print 4, potentially.
I can force the result of 3 if the multiplication by 100 is performed with double arithmetic instead of float:
f = Foo();
Console.WriteLine((int) ((double)f * 100)); // Prints 3
... but it's not clear to me why that's happening in the original version, given that float.Parse returns float, not double. At a guess, the result remains in registers and the subsequent multiplication is performed using double arithmetic (which is valid according to the spec) but it's certainly a surprising difference.
This happens because the float value is really more like 0.039999999999; you are therefore converting a value like 3.99999999999 to int, which yields 3.
You can solve the problem by rounding:
Console.WriteLine((int)Math.Round(float.Parse("0.04", System.Globalization.CultureInfo.InvariantCulture) * 100));
As a float 0.04*100 might well be represented as 3.9999999999, and casting to an int just truncates it, so that is why yo are seeing 3
It's actually not 4 but 3,99999 and lots of other numbers. Do something like this:
(int)(float.Parse("0.04") * 100.0 + 0.5)
Casting to float is like a floor operator and as this is not exactly 4 it is truncated to 3.

How to "round" a 2D Vector to nearest 15 degrees

I'm working on a simple game and I'm trying to simplify part of the 2D collision reaction in the game. When certain objects hit walls, I'm calculating a collision normal (collisionPoint - objectCenter) and reflecting based on that normal. I'm interested in rounding that normal vector to its nearest 15° but I'm not sure of a good way to go about that.
My current thought is doing something like this
float angle = atan2(normal.Y, normal.X) * Rad2Deg;
float newAngle = ((int)(angle + 7.5f) / 15) * 15.0f * Deg2Rad;
vector2 newNormal = vector2(cos(newAngle), sin(newAngle));
Is this a reasonable way to do it? Is there a better way?
Try this:
float roundAngle = 15 * Deg2Rad;
float angle = (float)Math.Atan2(normal.Y, normal.X);
Vector2 newNormal;
if (angle % roundAngle != 0)
{
float newAngle = (float)Math.Round(angle / roundAngle) * roundAngle;
newNormal = new Vector2((float)Math.Cos(newAngle), (float)Math.Sin(newAngle));
}
else
{
newNormal = Vector2.Normalize(normal);
}
You don't need to add 7.5, take this example:
// 4 degrees should round to 0
(4 + 7.5) / 15 == 11.5 / 15 == 0.77
// When this gets rounded up to 1 and multiplied by 15 again, it becomes 15 degrees.
// Don't add 7.5, and you get this:
4 / 15 == 0.27
// When rounded, it becomes 0 and, as such the correct answer
// Now how about a negative number; -12
-12 / 15 == -0.8
// Again, when rounded we get the correct number
actually this is more correct if you want the nearest 15 degree angle :
do this:
newangle% = INT(((angle%+7.5)/15)*15)
INT ALWAYS rounds DOWN by default this should properly give you the nearest angle in any case that is positive or negative have fun!!
and add the part where you use degree to rad and rad to degree if needed INSIDE the parens (like right next to angle% if that angle is not given in degrees then use some sort of rad2deg multiplier inside there
this is more like how you would do this in basic, with some modification It will work in c code or such, well good luck!!

Categories