C# float variable showing epsilon number - c#

i am facing a problem while assigning a large value to a float variable. Following is the code
float f1=99999999999.959f;
When i am retrieving value from this variable it is showing 1.0E+11 value. i want to get my original value. Can anyone help me to sort-out this problem.

In C#, float values only have a precision of 7 digits, so you're getting the best you can out of that data type. If you need more precision, use double or decimal.
http://msdn.microsoft.com/en-us/library/s1ax56ch.aspx

you are getting back the number you entered, to the degree of accuracy available from a float (about 6-7 d.p.)
So firstly, the storage of the value has limited precision, and secondly the way you display it may add further rounding.
If you use a double, you will increase the precision to around 15 d.p., or you can go further and use a decimal.

Primitives types float and double are approximations.
Here is a great response on their precision: How to Calculate Double + Float Precision
Even decimal has this problem. C# does not come with big num class, but you can use libraries for that. If you need more accurate decimal numbers then decimal (±1.0 × 10^−28 to ±7.9 × 10^28) you should try them.
Example: https://bcl.codeplex.com/ (BigRational)

Related

c# print float values with more precision

I want to print floats with greater precision than is the default.
For example when I print the value of PI from a float i get 6 decimals. But if I copy the same value from the float into a double and print it i get 14 decimals.
Why do I get more precision when printing the same value but as a double?
How can I get Console.WriteLine() to output more decimals when printing floats without needing to copy it into a double first?
I also tried the 0.0000000000 but it did not write with more precision, it just added more zeroes. :-/
My test code:
float x = (float)Math.PI;
double xx = x;
Console.WriteLine(x);
Console.WriteLine(xx);
Console.WriteLine($"{x,18:0.0000000000}"); // Try to force more precision
Console.WriteLine($"{xx,18:0.0000000000}");
Output:
3,141593
3,14159274101257
3,1415930000 <-- The program just added more zeroes :-(
3,1415927410
I also tried to enter PI at https://www.h-schmidt.net/FloatConverter/IEEE754.html
The binary float representation of PI is 0b01000000010010010000111111011011
So the value is: 2 * 0b1.10010010000111111011011 = 2 * 1.57079637050628662109375 = 3.1415927410125732421875
So there are more decimals to output. How would I get C# to output this whole value?
There is no more precision in a float. When you convert it to a double, the accuracy is worse, even though the precision (number of digits) increased - basically, all those extra digits you see in the double print are conversion artifacts - they are wrong, just the best representation of that given float number you can get in a double. This has everything to do with how binary floating point numbers work.
Let's look at the binary representation of the float:
01000000010010010000111111011100
The first bit is sign, the next eight are the exponent, and the rest is the mantissa. What do we get when we cast it to a double? The exponent stays the same, but the mantissa is filled in with zeroes. But that actually changes the number - you get 3.1415929794311523 (rounded, as always with binary floats) instead of the correct 3.14159265358979 double value of pi. You get the illusion of greater precision, but it's only an illusion - the number is no more accurate than before, you just replaced zeroes with noise.
There's no 1:1 mapping between floats and doubles. The same float value can be represented by many different double values, and the decimal representation of the number can change accordingly. Every cast of float to double should be followed by a rounding operation if you care about decimal precision. Consider this code instead:
double.Parse(((float)Math.PI).ToString())
Instead of casting the float to a double, I first changed it to a decimal representation (in a string), and created the double from that. Now instead of having a "truncated" double, you have a proper double that doesn't lie about extra precision; when you print it out, you get 3.1415930000. Still rounded, of course, since it's still a binary->decimal conversion, but no longer pretending to have more precision than is actually there - the rounding happens at a later digit than in the float version, the zeroes are really zeroes, except for the last one (which is only approximately zero).
If you want real decimal precision, you might want to use a decimal type (e.g. int or decimal). float and double are both binary numbers, and only have binary precision. A finite decimal number isn't necessarily finite in binary, just like a finite trinary number isn't necessarily finite in decimal (e.g. 1/3 doesn't have a finite decimal representation).
A float within c# has a precision of 7 digits and no more. That means 1 digit before the decimal and 6 after.
If you do have any more digits in your output, they might be entirely wrong.
If you do need more digits, you have to use either double which has 15-16 digits precision or decimal which has 28-29 digits.
See MSDN for reference.
You can easily verify that as the digits of PI are a little different from your output. The correct first 40 digits are: 3.14159 26535 89793 23846 26433 83279 50288 4197
To print the value with 6 places after the decimal.
Console.WriteLine("{0:N6}", (double)2/3);
Output :
0.666667

Convert float to double

I'm trying to convert Single to Double while maintaining the original value. I've found the following method:
Single f = 5.2F;
Double d1 = f; // 5.19999980926514
Double d2 = Double.Parse(f.ToString()); // 5.2 (correct)
Is this practice recommendable? I don't need an optimal method, but the intended value must be passed on to the double. Are there even consequences to storing a rounded value in a double?
You could use "decimal" instead of a string.
float f = 5.2F;
decimal dec = new decimal(f);//5.2
double d = (double)dec; //5.2
The conversion is exact. All the Single values can be represented by a Double value, because they are "built" in the same way, just with more possible digits. What you see as 5.2F is in truth 5.1999998092651368. If you go http://www.h-schmidt.net/FloatConverter/IEEE754.html and insert 5.2 you'll see that it has an exponent of 2^2 (so 4) and a mantissa of 1.2999999523162842. Now, if you multiply the two numbers you'll get 5.1999998092651368.
Single have a maximum precision of 7 digits, so .NET only shows 7 digits. With a little rounding 5.1999998092651368 is 5.2
If you know that your numbers are multiples of e.g. 0.01, I would suggest that you convert to double, round to the nearest integer, and subtract that to get the fractional residue. Multiply that by 100, round to the nearest integer, and then divide by 100. Add that to the whole-number part to get the nearest double representation to the multiple of 0.01 which is nearest the original number.
Note that depending upon where the float values originally came from, such treatment may or may not improve accuracy. The closest float value to 9000.02 is about 9000.019531, and the closest float value to 9000.021 is about 9000.021484f. If the values were arrived at by converting 9000.020 and 9000.021 to float, the difference between them should be about 0.01. If, however, they were arrived at by e.g. computing 9000f+0.019531f and 9000f+0.021484f, then the difference between them should be closer to 0.02. Rounding to the nearest 0.01 before the subtract would improve accuracy in the former case and degrade it in the latter.

Converting double to float in C# giving wrong values

Question is real simple. I have a double which I want to convert to float.
double doubleValue = 0.00000000000000011102230246251565;
float floatValue = (float)doubleValue;
Now when I do this. Float value just goes mad. Its value is "1.110223E-16" Do I need to do something extra for this flow. Value should be 0 or 0.1 but it is not here. What the problem here?
Converting double to float will definitely be loss of precision . But the value 1.110223E-16 is exponent notation i.e. raised to power -16 that means it is something like 0.0000000000000001110223.
You should use Math.Round() to round numbers.
The float is perfectly fine. It represents the value of the double up to the precision of a float.
1.110223E-16 is another notation for 0.0000000000000001110223.
Double is double-precision floating-point number but float is single-precision floating-point number.
So normally, you can loss precision when you convert Double to float. 1.110223E-16 is equal something like 0.0000000000000001110223 as it representation.
If you want to round the nearest number your values, you can use Math.Round() method.
Rounds a value to the nearest integer or to the specified number of
fractional digits.
Take a look at The Floating-Point Guide
A float is capable of representing about 6 significant figures with perfect accuracy. That's not the same thing as 6 decimal places which is what I think you were assuming.
Actually it is giving the right value.
How about getting rid of exponent after converting to float
double doubleValue = 0.00000000000000011102230246251565;
float result = (float)doubleValue;
decimal d = Decimal.Parse(result.ToString(), System.Globalization.NumberStyles.Float);

How to check if a double can fit into a float without conversion to infinity

Is there a standard way to check if a 64 bit floating point number can be converted to a 32 bit one without being converted to +/- Infinity?
I know it can be checked afterwards for +/- Inf.
Convert.ToSingle() won't do this.
In order to test whether a double value d will convert to float without yielding infinity, you can test whether d's absolute value is strictly below the double written as 3.4028235677973366e+38 (that is, 0x1.ffffffp+127 in hexadecimal). This number is the exact limit between doubles that can be converted to float and those that cannot.
To expand a little, the last finite float is:
0x1.fffffep+127 (3.4028234663852886e+38 in decimal)
What would be the next float number if type float had more exponent bits is:
0x2.000000p+127 (3.4028236692093846e+38 in decimal)
The numbers that are closer to the former than to the latter are rounded down to the former. The limit is the midpoint of the two numbers:
0x1.ffffffp+127 (3.4028235677973366e+38 in decimal)

Why 1.0f + 0.0000000171785715f returns 1f?

After one hour of trying to find a bug in my code I've finally found the reason. I was trying to add a very small float to 1f, but nothing was happening. While trying to figure out why I found that adding that small float to 0f worked perfectly.
Why is this happening?
Does this have to do with 'orders of magnitude'?
Is there any workaround to this problem?
Thanks in advance.
Edit:
Changing to double precision or decimal is not an option at the moment.
Because precision for a single-precision (32 bit) floating-point value is around 7 digits after the decimal point. Which means the value you are adding is essentially zero, at least when added to 1. The value itself, however, can effortlessly stored in a float since the exponent is small in that case. But to successfully add it to 1 you have to use the exponent of the larger number ... and then the digits after the zeroes disappear in rounding.
You can use double if you need more precision. Performance-wise this shouldn't make a difference on today's hardware and memory is often also not as constrained that you have to think about every single variable.
EDIT: As you stated that using double is not an option you could use Kahan summation, as akuhn pointed out in a comment.
Another option may be to perform intermediary calculations in double-precision and afterwards cast to float again. This will only help, however, when there are a few more operations than just adding a very small number to a larger one.
Floating-point arithmetic
This probably happens because the number of digits of precision in a float is constant, but the exponent can obviously vary.
This means that although you can add your small number to 0, you cannot expect to add it to a number that has an exponent different from 0, since there just won't be enough digits of precision left.
You should read What Every Computer Scientist Should Know About Floating-Point Arithmetic.
It looks like it has something to do with floating point precision. If I were you, I'd use a different type, like decimal. That should fix precision errors.
With float, you only get an accuracy of about seven digits. So your number'll be rounded into 1f. If you want to store such number, use double instead
http://msdn.microsoft.com/en-us/library/ayazw934.aspx
In addition to the accepted answer: If you need to sum up many small number and some larger ones, you should use Kahan Summation.
If performance is an issue (because you can't use double), then binary scaling/fixed-point may be an option. floats are stored as integers, but scaled by a large number (say, 2^16). Intermediate arithmetic is done with (relatively fast) integer operations. The final answer can be converted back to floating point at the end, by dividing by the scaling factor.
This is often done if the target processor lacks a hardware floating-point unit.
You're using the f suffix on your literals, which will make these floats instead of doubles. So your very small float will vanish in the bigger float.

Categories