C# Math Problem - c#

I have been working on this for the greater part of the day and I cant seem to make this part of my code work. The intent of the code is to allow the user to input a set of values in order to calculate the missing value. As an additional feature I placed a CheckBox on the form to allow the user to do further calculation. That is where my problem lies. I know the code works because if I change the formula the value that appears in tb3_aic.Text changes per the formula. However, when I use the below the answer does not change like it should. Please reference the attached code. If a jpg image is needed of the formula I can e-mail it.
void Calc3Click(object sender, EventArgs e)
{
if (String.IsNullOrEmpty(tb3_skv.Text) | String.IsNullOrEmpty(tb3_kva.Text) | String.IsNullOrEmpty(tb3_z.Text))
{
MessageBox.Show("Enter all required values", "Missing Data", MessageBoxButtons.OK);
} //If user does not enter all the values required for the calculation show error message box
else
{
if (!String.IsNullOrEmpty(tb3_skv.Text) & !String.IsNullOrEmpty(tb3_kva.Text) & !String.IsNullOrEmpty(tb3_z.Text))
{ //If motor load check box is not checked and required values are entered calculate AIC based on formula.
int y;
decimal x, z, a;
x = decimal.Parse(tb3_skv.Text);
y = int.Parse(tb3_kva.Text);
a = decimal.Parse(tb3_z.Text);
z = (y * 1000) / (x * 1.732050808m) / (a / 100); //the m at the end of the decimal allows for the multiplication of decimals
tb3_aic.Text = z.ToString();
tb3_aic.Text = Math.Round(z,0).ToString();
}
if (cb3_ml.Checked==true)
{//If Motor Load CB is checked calculate the following
int y, b;
decimal x, z, a;
x = decimal.Parse(tb3_skv.Text);
y = int.Parse(tb3_kva.Text);
a = decimal.Parse(tb3_z.Text);
b = int.Parse(tb3_ml.Text);
z = ((y * 1000) / (x * 1.732050808m) / (a / 100))+((b / 100)*(6*y)/(x*1.732050808m)*1000);
tb3_aic.Text = z.ToString();
tb3_aic.Text = Math.Round(z,5).ToString();
}
}
I am grateful for any help that can be provided.
Thank you,
Greg Rutledge

Without really knowing what the problem is, a few things look a bit odd:
Also, mixing decimal and int in a calculation can lead to unexpected results unless you really know what you are doing. I suggest using only decimals (or doubles, which are way faster and usually have enough precision for engineering computations).
You also set tb3_aic.Text twice, I assume you decided on rounding later and forgot to remove the first one.
Edit: This is apparently wrong in C#:
You use bit-wise AND (&) in the if-clause where you probably mean logical AND (&&).
The only difference between them when used with boolean operands are that && short circuits (doesn't evaluate the right operand if the left is false). I learned something, thank you people commenting. :)

Change this:
int y, b;
To this:
int y;
decimal b;
and it works, according to this test:
public void Test2()
{
int y;
decimal b;
decimal x, z, a;
decimal z1, z2;
x = 480m;
y = 2500;
a = 5.75m;
b = 10;
z1 = ((y * 1000) / (x * 1.732050808m) / (a / 100));
z2 = ((b / 100) * (6 * y) / (x * 1.732050808m) * 1000);
z = z1 + z2;
Console.WriteLine("{0}, {1}", z1, z2);
Console.WriteLine(Math.Round(z, 0).ToString());
}
The reason is that integer 10 divided by integer 100 is integer 0, which zero's the whole z2.

I don't know if this is huge but you are setting the text of the tb3_aic textbox twice when maybe you are trying to concatenate?
tb3_aic.Text = z.ToString();
tb3_aic.Text = Math.Round(z,0).ToString();
You seem to be doing this in both methods.
The more that I look at it, this could be an issue since you are setting it in the first if then the second If will overwrite that if the checkbox is checked.

Sample Inputs, first formula
x = 480
y = 2500
a = 5.75
For the first formula the output should be 52296
Sample Inputs, second formula
x = 480
y = 2500
a = 5.75
b = 10
For the first formula the output should be 54100.42
Hope this helps

this line isn't needed, although its not a bug, it just always evaluates to true
if (!String.IsNullOrEmpty(tb3_skv.Text) & !String.IsNullOrEmpty(tb3_kva.Text) & !String.IsNullOrEmpty(tb3_z.Text)) {

Related

Compare Voctor.y

Hey i'm comparing 2 Vector.y's but it isnt working!
Here the code:
print(last.y + " == " + controller.transform.position.y);
if (last.y == controller.transform.position.y)
The print: 0,7999999 == 0,7999999
You are comparing floating point numbers. To get those exactly equal is hard. Unity only shows a limited amount of decimals in the editor. Try rounding the numbers.
https://docs.unity3d.com/ScriptReference/Mathf.Round.html
I.e.:
float randomNumber = 2.543686;
randomNumber = Mathf.Round(randomNumber * 100.0) / 100.0;
will return 2.54
Depending on how precise you want you could also do:
// If absolute difference between last y and controller pos y is less than 0.0001
if (Mathf.abs(last.y - controller.transformer.position.y) < 0.0001f) {
// do something
}

Float overflow in C#

What happens if I try to stuff a number bigger than float.MaxValue in a float?
I have this in my code:
int a;
float x;
float y;
...
float b = (a * x) / y;
I have two questions about this:
Is the result of (a * x) stored in a temp bigger than a float? And is this only done when the result passes float.MaxValue?
Do I get an exception when the result of the sum is stuffed into a? And if not, how should I handle this to prevent disaster?
You'll get float.PositiveInfinity (or float.NegativeInfinity)... Or you'll just remain in float.MaxValue (float.MaxValue + 1 == float.MaxValue)... floating points have a "resolution", that becomes lower the greater the floating point is... The distance between the last two floating points is about...
3,40282347E+38: float.MaxValue
3,40282326E+38: previous float
2,028241E+31: difference <--------- 2*2^31!
calculated through
float nearMaxValue = BitConverter.ToSingle(BitConverter.GetBytes(BitConverter.ToInt32(BitConverter.GetBytes(float.MaxValue), 0) - 1), 0);
Console.WriteLine("{0:R}: float.MaxValue", float.MaxValue);
Console.WriteLine("{0:R}: previous float", nearMaxValue);
Console.WriteLine("{0:R}: difference", float.MaxValue - nearMaxValue);
If you try to put inside a float a number bigger than float.MaxValue, it will be "Infinity"
Yes, the calculation is indeed done in the computer's memory. This is always the case.
No, an overflow does not cause an exception.
As for what will happen if you run this code snippet (after cleaning up the errors):
float b = (a * x) / y;
Console.WriteLine(b);
Output: +infinity
a = (int)b;
Console.WriteLine(a);
Output: -2147483648

Does Convert.ToSingle() then System.Convert.ToString() cause miscalculation for Double input?

I know title is not clear enough , let me explain. I'm working on a project about an iterative algorithm to compute geodetic coordinates and this is the first part of it. Basically program is doing some iterative calculations using the textbox inputs. It converts textbox input to Single , uses it for calculation and then converts to String as an output. At some points , I need to use an output as an input for following processes but the problem is , it gives slightly different results. For example , these are the results of an online calculator for x,y,z : 1114125.84474949 , -4844708.42056692 , 3982826.71498173 ; and these are mine 1114125.55452963 , 4844708.5526556 , 3982826.75245773. What causes this? (don't mind the missing minus of y). To sum up , i wonder if converting textbox texts to single then , converting them to string cause this error or not. I hope question is clear.
Here is a part of codes which gave the results I mentioned above. More complicated iterations will also work like this , if I can solve the issue.
private void button1_Click_1(object sender, EventArgs e)
{
this.timer1.Start(); // it's beside the point
double fi = Convert.ToSingle(phi.Text);
double lamda = Convert.ToSingle(lambda.Text);//lamda is input, lambda is textbox
double yuk = Convert.ToSingle(height.Text);
double a = Convert.ToSingle(aa.Text);
double b = Convert.ToSingle(bb.Text);
double ec = (Math.Pow(a, 2) - Math.Pow(b, 2)) / Math.Pow(a, 2); //eccentricity
double N = a / Math.Sqrt(1 - ec * Math.Pow(Math.Sin((Math.PI / 180) * fi), 2));
double xx = ((N + yuk) * Math.Cos((Math.PI / 180) * fi) * Math.Cos((Math.PI / 180) * lamda));
double yy = ((N + yuk) * Math.Cos((Math.PI / 180) * fi) * Math.Sin((Math.PI / 180) * lamda));
double zz = ((Math.Pow(b/a,2) * N + yuk) * Math.Sin((Math.PI / 180) * fi));
coorx.Text = System.Convert.ToString(xx); //xx, yy, zz are textboxes
coory.Text = System.Convert.ToString(yy);
coorz.Text = System.Convert.ToString(zz);
}
Computer use binary format in order to store numbers in the memory, in additon there is limited number of bits that are used to store these values (depend on the type which use), therefore conversion of the string value, which is given in decimal number format, and is of single / double type (so real value number) is usally related with degradation of precision.

When incrementing a double value in a for loop, how can I make sure it stays relatively round?

I have this for loop:
for (double x = -1 * (display.Width / zoom); x <= (display.Width / zoom); x += 0.1)
{
//..
}
x is initialized to -20 and is compared against 20. Ideally, I would like x to be incremented as -20, -19.9, -19.8, etc. In practice, this is not what happens; on some iterations, there is indeed only one digit after the decimal point, but in others, it is not as precise, for example -19.8999999. This is responsible for some very irritating (and hard to find) bugs in my program.
How can I make it so that x stays 'relatively round'?
Don't use double or float if you need this kind of accuracy - use decimal instead.
This is happening because certain fractions cannot be accurately represented in binary - I suggest reading What Every Computer Scientist Should Know About Floating-Point Arithmetic.
This has to do with the way a double is stored. Try a decimal instead.
Use integer loop counter, initialized to -200 and compared against 200, and calculate your real x in each iteration.
UPD: using Decimal is probably better.
If i understand you right... why you just round it?
Math.Round(x,1)
Floating point numbers (Double/Float) aren't accurate, instead use -200 and 200 as an int. That will allow to not have to worry about lack of floating point precision.
For more information about this imprecision, I suggest this document.
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html
IF you really want it as precise as possible scale it up so that you can work with int or long... for example:
long _Z = (long) ((display.Width * 10) / zoom);
for (long _x = -1 * _Z; _x <= _Z; _x += 1)
{
double x = ((double)_x) / 10.0;
// ...
}
if you must use double you could use like this:
double x = 0.0;
while (x <= 3.0)
{
//Do your stuff
x = Math.Round(x + 0.1, 1);
}

Why is modulus operator not working for double in c#?

Consider this:
double x,y;
x =120.0;
y = 0.05;
double z= x % y;
I tried this and expected the result to be 0, but it came out 0.04933333.
However,
x =120.0;
y = 0.5;
double z= x % y;
did indeed gave the correct result of 0.
What is happening here?
I tried Math.IEEERemainder(double, double) but it's not returning 0 either. What is going on here?
Also, as an aside, what is the most appropriate way to find remainder in C#?
Because of its storage format, doubles cannot store every values exactly as is is entered or displayed. The human representation of numbers is usually in decimal format, while doubles are based on the dual system.
In a double, 120 is stored precisely because it's an integer value. But 0.05 is not. The double is approximated to the closest number to 0.05 it can represent. 0.5 is a power of 2 (1/2), so it can be stored precisely and you don't get a rounding error.
To have all numbers exactly the same way you enter / display it in the decimal system, use decimal instead.
decimal x, y;
x = 120.0M;
y = 0.05M;
decimal z = x % y; // z is 0
You could do something like:
double a, b, r;
a = 120;
b = .05;
r = a - Math.floor(a / b) * b;
This should help ;)
I believe if you tried the same with decimal it would work properly.
http://en.wikipedia.org/wiki/Floating_point#Accuracy_problems can help you understand why you get these "strange" results. There's a particular precision that floating point numbers can have. Just try these queries and have a look at the results:
0.5 in base 2
0.05 in base 2
Modulus should only be used with integer. The remainder come from an euclidean division. With double, you can have unexpected results.
See this article
This is what we use.. :)
public double ModuloOf(double v1, double v2)
{
var mult = 0;
//find number of decimals
while (v2 % 1 > 0)
{
mult++;
v2 = v2 * 10;
}
v1 = v1 * Math.Pow(10, mult);
var rem = v1 % v2;
return rem / Math.Pow(10, mult);
}

Categories

Resources