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
Related
So, I'm a tad confused. I was under the impression that this should work:
In this case, both a and b are ints (Counters to be exact).
As the result of a / b may possibly contain decimal places, ints obviously won't work.
Therefore, I delared a new double and performed the calculation inside it like this:
double texturefactor = ((a / b) * 10);
This doesn't work as I expected, and the result of a / b is always that which I would get if I performed the calculation using an int to store the results.
On the other hand, this works:
double calculate1 = a;
double calculate2 = b;
double texturefactor = ((calculate1 / calculate2) * 10);
Couple of perhaps stupid questions-
1. I'm sure this ought to work- I know that in certain situations VS will complain that I've tried to implicitly convert from one type to another- That's what I'm trying to do! Why doesn't it, and have I missed something? :)
2. Should I just convert the counters a and b to doubles and save myself the trouble of the conversion, or is that trouble?
The result of a / b is another integer, so even if you do this, the damage has already been done:
double texturefactor = ((a / b) * 10);
Try casting one of your inner variables to a double:
var texturefactor = (( (double)a / b) * 10);
The result of (double)a / b will be a double, and you won't lose your fraction.
To answer your second question:
Should I just convert the counters a and b to doubles
That'd work too. If you change those to double, then you wouldn't have to perform the above cast.
The expression, including the types of subexpressions, is evaluated from inside to outside:
double texturefactor = ((a / b) * 10);
When the compiler analyses a / b, it has no idea that the result will later on be converted to double, so it just compiles the computation as an integer division.
Explicitly casting one of the two operands to double right there is enough to avoid that confusion:
double texturefactor = (((double)a / b) * 10);
When you have the expression (a / b), the C# compiler ignores that it will later be assigned to a double. It focuses only on that expression, and sees int / int, so it uses integer division. This means that your result is rounded down to the next integer before it's ever converted to a double.
You need to make sure C# treats the division as a division of doubles, not ints, for example:
double texturefactor = (((double)a / b) * 10); // or
double texturefactor = 10d * a / b; // or
double texturefactor = 10.0 * a / b;
The reason this double texturefactor = ((a / b) * 10); not working is that all the parameters on the right hand side are of type int thus the calculations are being done in int not double as you think.
You can explicitly cast a or b to double. Like
double texturefactor = (((double) a / b) * 10);
In your second code since you defined a and b as double, now the calculations are done in double type.
You need to cast the int values to double:
int a = some_value;
int b = some_value;
double texturefactor = (double)a / b * 10;
Integer division will not have decimal values just because you are assigning their values to a double variable.
If you want precision, then your second method is quite good.
double calculate1 = a;
double calculate2 = b;
double texturefactor = ((calculate1 / calculate2) * 10);
The above is good.
I will not advise you to cast it into double as there is some overhead to pay.
Result of dividing two integers is always a integer. So you need to
double texturefactor = (((double)a / b) * 10);
Therefore, I delared a new double and performed the calculation inside it like this:
Ah, no.
double texturefactor = ((a / b) * 10);
Basic syntax. YOu declare a double (texturefactor). You assign it the result of a pure integer opeation - (a/b)*10
Due to precedences this is a/b (integer, throw away digits) times 10. THEN implicit converison.
Typical beginner mistake - but one MANY do.
You want a double arithmetic, make sure any of the elements is a double, like for example:
((double) a/b)*10
will do a floating piont conversion for all elements.
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);
}
I have a calculation for example 2/4 = 0.5, except I can't find a data type that will store this value! Every time I make the calculation it says 0.
Anyone have any suggestions?
Either double or decimal will work fine.
However, if you just write:
// Wrong
double x = 2 / 4;
then it will still use integer division - because both of the operands for the division operator are of type int.
You can either cast either or both of the operands to double, or use a double literal for either or both of them:
// Any of these...
double x = (double) 2 / 4;
double x = 2 / (double) 4;
double x = (double) 2 / (double) 4;
double x = 2.0 / 4;
double x = 2 / 4.0;
double x = 2.0 / 4.0;
double x = 2d / 4;
double x = 2 / 4d;
double x = 2d / 4d;
Note that both double and decimal are floating point types. They don't represent arbitrary rational numbers (fractions). For example, neither can accurately represent 1/3. If you need a rational number type, you'll have to write your own or look for a third party implementation.
Make sure at least one of the divisor or the dividend is a floating number:
double d = 2 / 4.0;
Console.WriteLine(d): // Writes: 0.5
Use 2/4.0 to force it to use floating point arithmetics. Then you can store it in a double:
double d = 2/4.0;
If in the real code you have variables, cast the divisor to a double:
int i = 2;
int j = 4;
double d = i/(double)j;
You can cast,
double value = (double)2/4;
or you can provide your input with decimals
double value = 2.0/4.0;
Either float or double will do the job.
float x = 2f / 4f;
double x = 2d / 4d;
Note that you can specify constant values to be float or doubles by appending the appropriate character (f or d).
The important thing to remember is that the first data type (on the left) will determine the data type of the result. EDIT: actually, in this case either value being a float/double will work
So...
var x = 2 / 4;//x is int (0)
var x = 2f / 4;//x is float (0.5f)
var x 2d / 4;//x is double (0.5d)
C# will automatically convert int to float/double so...
float x = 2 / 4;//result type is int, but gets stored as convert float
Anyway, hope that helps explain some things
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);
}
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)) {