This question already has answers here:
Difference between decimal, float and double in .NET?
(18 answers)
Closed 9 years ago.
Consider this program
float a = 0.7f;
if (a < 0.7)
{
Console.WriteLine("Less");
}
The output is Less. Why??
Because 0.7 does not have an exact representation as a float or a double: it is not an exact sum of negative powers of 2.
It happens that the closest representation of 0.7 as a is float approximately 0.69999998807907104492, while the closest double representation is 0.69999999999999995559. As you can see, double is slightly greater, which explains the behavior of your program.
Here is a small demo that you could run to see the values on your system:
printf("%20.20f %20.20f\n", 0.7, (float)0.7);
(live demo on ideone).
The takeaway lesson here is that you should not expect double and float representations of mathematically equal numbers to compare for equality correctly. Only a small subset of fractional numbers are representable in floating point system as exact numbers.
Since the overwhelming majority of fractions would be approximated, it is a good idea to do the comparisons with some level of tolerance. For example, instead of writing if (a == 0.7) you should write if (abs(a - 0.7) < 1E-8)
You're unknowingly comparing apples and potatoes in your code.
float a = 0.7f; // "0.7f" is a float
if(a< 0 .7) // "0.7" is a double
{
Console.WriteLine("Less"); //You'll see it because of different representations
}
Your check will work as you expect if you match the number types:
float a = 0.7f;
if(a < 0.7f)
{
Console.WriteLine("Less"); // You won't see this
}
This is why numbers should never be hard-coded. Best way to fix your code:
float check = 0.7f;
float a = 0.7f;
if(a < check)
{
Console.WriteLine("Less"); // You won't see this either
}
Related
I wrote this simple rounding method in C#, which will round any floating point number (input) to the nearest multiple of any target number (target):
float RoundToFloat(float input, float target)
{
float quotient = input / target;
if (quotient - Mathf.Floor(quotient) < .5)
{
return Mathf.Floor(quotient) * target;
}
else
{
return Mathf.Ceil(quotient) * target;
}
}
However this seems to break when the input is a negative number. What do I have to do to make it work? I've tried calculating the absolute value of the quotient, and flipping whether I use ceil / floor if the input is negative, but keep getting weird results either way.
Any advice would be much appreciated!
Got it ... you need to reverse the applications of Floor and Ceiling for negative numbers, because the rounding has to be in the 'correct direction' with respect to 0.
Floor always goes more negative, while Ceiling does the opposite.
You can do this with a "simple" addition to your if: an "iff", also known as "Boolean equals".
if (quotient - Mathf.Floor(quotient) < .5) ==
(quotient >= 0) {
C# code:
double value = float.MaxValue;
Console.WriteLine(value / 2);
give different values (C# gives 1.70141173319264E+38 and C# without floats gives me 1.701411735e+38) me .
When I use the c# code:
double value = 3.40282347E+38;
Console.WriteLine(value / 2);
I get the same as floats. Is MSDN wrong?
Dot Net Fiddle
float.MaxValue is 3.40282347E+38.
Float MaxValue
Fiddling around I found that
Console.WriteLine(((3.40282347E+38 / 2) == (float.MaxValue / 2)).ToString()); prints False while Console.WriteLine(((3.40282347E+38f / 2) == (float.MaxValue / 2)).ToString()); prints True. It's because the language does this:
By default, a real numeric literal on the right side of the assignment operator is treated as double.
Your number is a double and you are comparing it against a float, so the precision is different by default. You have to force the number to be a float by adding f on the end of it.
I have interprated the formula in wikipedia in c# code, i do get a nice normal curve, but is it rational to get values that exceeds 1? isnt it suppose to be a distribution function?
this is the C# implementation :
double up = Math.Exp(-Math.Pow(x , 2) / ( 2 * s * s ));
double down = ( s * Math.Sqrt(2 * Math.PI) );
return up / down;
i double checked it several times and it seems fine to me so whats wrong? my implementation or understanding?
for example if we define x=0 and s=0.1 this impl would return 3.989...
A distribution function, a pdf, has the property that its values are >= 0 and the integral of the pdf over -inf to +inf must be 1. But the integrand, that is the pdf, can take any value >= 0, including values greater than 1.
In other words, there is no reason, a priori, to believe that a pdf value > 1 indicates a problem.
You can think about this for the normal curve by considering what reducing the variance means. Smaller variance values concentrate the probability mass in the centre. Given that the total mass is always one, as the mass concentrates in the centre, the peak value must increase. You can see that trend in the graph the you link to.
What you should do is compare the output of your code with known good implementations. For instance, Wolfram Alpha gives the same value as you quote: http://www.wolframalpha.com/input/?i=normal+distribution+pdf+mean%3D0+standard+deviation%3D0.1+x%3D0&x=6&y=7
Do a little more testing of this nature, captured in a unit test, and you will be able to rely on your code with confidence.
Wouldn't you want something more like this?
public static double NormalDistribution(double value)
{
return (1 / Math.Sqrt(2 * Math.PI)) * Math.Exp(-Math.Pow(value, 2) / 2);
}
Yes, it's totally OK; The distribution itself (PDF) can be anything from 0 to +infinity; the thing should be in the range [0..1] is the corresponding integral(s) (e.g. CDF).
You can convince yourself if look at the case of non-random value: if the value is not a random at all and can have only one constant value the distribution degenerates (standard error is zero, mean is the value) into Dirac Delta Function: a peak of infinite hight but of zero width; integral however (CDF) from -infinity to +infinity is 1.
// If you have special functions implemented (i.e. Erf)
// outcoume is in [0..inf) range
public static Double NormalPDF(Double value, Double mean, Double sigma) {
Double v = (value - mean) / sigma;
return Math.Exp(-v * v / 2.0) / (sigma * Math.Sqrt(Math.PI * 2));
}
// outcome is in [0..1] range
public static Double NormalCDF(Double value, Double mean, Double sigma, Boolean isTwoTail) {
if (isTwoTail)
value = 1.0 - (1.0 - value) / 2.0;
//TODO: You should have Erf implemented
return 0.5 + Erf((value - mean) / (Math.Sqrt(2) * sigma)) / 2.0;
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
C# float bug? 0.1 - 0.1 = 1.490116E-08
problem in comparing double values in C#
In my application I want to test if float a=float b, and then do some operations. But, I wonder, that in float type 0.2+0.3==0.5 is returning false .
So here is some part of my code
float a = 0.3f;
float b = 0.2f;
float c = 0.5f;
if (a + b == c)
Console.WriteLine("true");
else
Console.WriteLine("false");
Console.WriteLine(a+b);
Console.WriteLine(c);
And here is result of this part
false
0.5
0.5
I can't figure out what is wrong here... I can use double or decimal instead float, but I want to know what's wrong here.
Thanks for help.
Floats are not exact values, they are approximates. It could be that the equation is 0.30000001 + 0.20000003 (= 0.50000004) == 0.50000001 which results in a false.
You should check if the difference between the 2 values is really small. More info here
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
C# Double - ToString() formatting with two decimal places but no rounding
I'm using float numbers and I want to get the number of decimal points without any rounding-off being performed.
For Eg. float x = 12.6789
If I want upto 2 decimal points, then I should get (x = 12.67) and NOT (x = 12.68) which happens when rounding takes place.
Plz suggest which is the best way to do this.
You should be able to use Math.Truncate() for this:
decimal x = 12.6789m;
x = Math.Truncate(x * 100) / 100; //This will output 12.67
You can achieve this by casting:
float x = 12.6789;
float result = ((int)(x * 100.0)) / 100.0;
There is probably a framework call for this, but you could always write one like:
//Scale up, floor, then round down.
//ie: 1.557
// scaled up: 155.7
// floord: 155
// scaled down: 1.55
public float MyTruncate(float f, int precision){
float scale = precision * 10;
return (Math.Floor(f * scale)) / scale;
}