Printing double values - c#

On my system, the following code prints '3.6':
double a = 1.2;
int b = 3;
double c = a * b;
Console.WriteLine(c);
But in the debugger, I can see that c has a value with more than 2 digits:
I know that I can display the full representation with Console.WriteLine("{0:R}", c). Is this the only and recommended way to display the actual value of a double?
update
Going with the above example, I'd like to print c such that if the user were to take the printed value and insert that back into the code in a test using ==, the comparison would be true. In this case c == 3.5999999999999996 returns true.

Console.WriteLine calls Double.ToString which uses the the "G" format specifier. This uses the current culture to determine the number of decimal places (1 for "en-US").
If you want to display 8 decimal places you can use the numeric format specifier:
Console.WriteLine(c.ToString("N8"));
Standard Numeric Format Strings
Edit: The debugger uses this method to convert a double to a string:
_ecvt_s
I assume it's the cheapest way to convert it.
Where i have found it: How does Visual Studio display a System.Double during debugging?

3.999999999999996 is not the actual value of the double either; that's just the value rounded off to fifteen places or whatever. There is no built-in way to display the actual exact value that the double is representing. This is really too bad, because every normal double can be represented exactly as a decimal string, and it would be nice to be able to see that.
As a public service, I've put source code for a device which does that on my blog:
http://ericlippert.com/2011/02/17/looking-inside-a-double/
Note that it uses the Rational class from Microsoft Solver Foundation. If you don't have that then you can either download it for free, or write your own Rational class; it's character-building to do so.
If the subject of how doubles work internally interests you, consider checking out my archive of handy articles explaining all that. It's at:
http://blogs.msdn.com/b/ericlippert/archive/tags/floating+point+arithmetic/
Start from the bottom; those are in reverse-chronological order.

You could also use a different approach for example if you want to return 2 decimal places you could try something like this
double a = 1.2;
int b = 3;
double c = a * b;
var s = string.Format("{0:0.00}", c);
Console.WriteLine(s);
Output = 3.60
if you want to suppress the last 0 where out put is 3.6 you could do
var s = string.Format("{0:0.##}", c);
Output = 3.6 feel free to play around with it

double a = 1.2;
int b = 3;
double c = a * b;
string formatted = c.ToString("N5");
Console.WriteLine(formatted);

Related

Get string from large double value(C#)

Can't find simple way to convert double to string. I need to convert large numbers without distortion. Such as:
double d = 11111111111111111111;
string s = d.ToString();
Console.WriteLine(s);
//1.11111111111111E+19
How to get string value from double value exactly the same as user enter.
11111111111111111111111 => "11111111111111111111111"
1.111111111111111111111 => "1.111111111111111111111"
Any ideas how it can be done?
double is a floating point type. So it has a limited accuracy. In your example, you could do something like this:
double d = 11111111111111111111;
string s = d.ToString("F0");
Console.WriteLine(s);
But as you'll see,this would output 11111111111111100000 instead of 11111111111111111111,so it has lost accuracy in the process. So the answer here is use the right type for the work. If you need a string, use a string variable to store the value.
Edit
This was the question i was trying to find that explains the problem with floating point math., thanks to #GSerg
First of all: 11111111111111111111111 is to large for a double value and also this value: 1.111111111111111111111 since the double max decimal length is 17.
By default, a Double value contains 15 decimal digits of precision,
although a maximum of 17 digits is maintained internally.
For this reason you should use BigInteger and then ToString for formatting the output.
There is also a library in the nuget Directory called BigRational, never used and seems in Beta stage but probably will help in solving this problem.
In general case, you can't do this: user can well input, say 123, in many a way:
123
123.00
1.23e2
12.3E1
123.0e+00
1230e-1
etc. When you convert the user input into double you loose the initial format:
string userInput = ...
// double is just 123.0 whatever input has been
double value = double.Parse(userInput);
In case you want to drop exponent if it's possible you can
double value = 11111111111111111111;
string result = value.ToString("#######################");
And, please, notice, that double has 64 bit to store the value, that's why a distortion is inevitable for large numbers:
// possible double, which will be rounded up
double big = 123456789123456789123456789.0;
// 1.2345678912345679E+26
Console.WriteLine(big.ToString("R"));
// 123456789123457000000000000
Console.WriteLine(big.ToString("###########################"));
May be you want BigInteger instead of double:
using System.Numerics;
...
BigInteger value = BigInteger.Parse("111111111111111111111111111111111");
// 111111111111111111111111111111111
Console.WriteLine(value.ToString());

How to add two float numbers with currency sign?

anyone knows how to add two float numbers with currency sign and place the sum into a dataGridview cell?
this is my code:
private void button8_Click(object sender, EventArgs e)
{
double a =0.70;
double b = 0.50;
dataGridView2.Rows[0].Cells[1].Value = "£" + (a+b);
}
if I declare a and b as float it gives error.
if I declare a and b as Double, the result is £1.2 as shown in photo but NOT £1.20 .
I made column 1 properties to contain a currency value ( result = £1.2)
I made column 1 properties to contain a numeric value and the result is same.
how can I make it £1.20?
is there any way to do it?
thank you
The double type doesn't keep track of how many decimal places were there when the result was computed. As far as it is concerned, 1.2 and 1.20 and 1.200 are all the same value.
You want a specific string representation of that number, with exactly two decimal places. The easiest way to get the desired string representation is using a format string. For example, you can do this:
(a + b).ToString("0:00");
In cases where you want to format multiple expressions, you may find this alternative more convenient:
string.Format("{0:0.00} {1:0.00} {2:0.0}", a, b, a + b)
Keep in mind that float and double are tricky. You probably want to handle money using the decimal type instead.
You can use:
dataGridView2.Rows[0].Cells[1].Value = (a + b).ToString("'£'0.00"));
To do this, you need to set a format for the string. Try using this:
dataGridView2.Rows[0].Cells[1].Value = string.Format("£{0:0.00}", a + b)
You can try this:
dataGridView2.Rows[0].Cells[1].Value = "£" + (a+b).ToString("0.00");
Thank you all for your help. now it is solved. I played around with cell format type and suddenly it changed to £1.20.
Definitely keep in mind the explanations given by Theodoros, especially the suggestion to use the decimal type.
That said, an alternative is to use a System.Globalization.CultureInfo. This has the advantage of correctly handling the symbol, decimal digits, decimal separator, group separator, and group sizes. This way you see results such as £1,234,567.89 instead of £1234567.89.
CultureInfo gb = new CultureInfo("en-GB");
string result = (a + b).ToString("c", gb.NumberFormat);
A further advantage is that parsing out the original value is just as easy:
decimal amount = Decimal.Parse(result, NumberStyles.Currency, gb);

Rounding to 2 decimal places c#

Currently have a working rounding model within my c# code and is perfectly rounding numbers that have more than 2 decimal places down to 2 decimal places which is great. However, when i have lets say double value = 100.6, and i put that into double dollar_value = Math.Round(value, 2), it still returns as 100.6.
I was wondering if there was a way to transform a 1 decimal place value to 2 decimal places?
Numbers are not stored with extra zeroes (As it is a waste of memory to do so, being the numbers are the same with or without). In order to represent a number this way you will either need to display or store it as a string.
string str = value.ToString("#.00", CultureInfo.InvariantCulture);
Now str will always have 2 decimal places.
I don't know the C# method, but in C++ I'd use one of these two methods:
double value = 23.666666 ; // example
value = 0.01 * floor ( value * 100.0 ) ; // There's a "floor" function in C# too
^ See https://msdn.microsoft.com/en-us/library/e0b5f0xb(v=vs.110).aspx
Or
double value = 23.666666 ; // example
value = 0.01 * (double) ( (int)(value*100.0) ) ;
Or
double value = 23.666666 ; // example
value = 0.01 * double ( int ( value*100.0 ) ) ; // same as previous, but more C++ like
The other answers are probably better if you're looking to "print a dollar amount with two decimal places." However, if you want to transform the number to use internally, this is a way to do it.
If you want the string representation to have two decimal points use:
yourNumber.ToString ("0.00");
The number itself is always stored as a ~29 digit number regardless of its string representation.
Your value just needs to be formatted when it's display - for example value.ToString("N2") will convert it to a string with two decimal places. Check out the Standard Numeric Format Strings on MSDN to see a broader list of formatting strings.
Additionally, I'd only convert to a string when you're ready display the value to a user and would keep it as a numeric type (e.g. double) if you're passing it around between methods or planning to do any further calculations on it. Otherwise you'll be unnecessarily converting the value to and from a string multiple times.

input string is not in a correct format

I want to calculate the percentage. But the compiler is giving an error that the input string is not in a correct format. Can some one elaborate what i am missing here?
private double per()
{
double a = Convert.ToDouble(tbEnglish.Text+tbUrdu.Text+tbPhysics.Text+tbChemistry.Text+tbMaths.Text);
double d = 500;
double lblResult = (a / d)*100;
return lblResult;
}
You're concatenating the strings and then trying to convert that one result into a double. So for results of 75.6, 92.1, 56.3 78.2 and 72.3 you'd end up trying to parse "75.692.156.378.272.3".
Parse each value and then sum them.
However, I would strongly recommend that you use decimal for this instead of double. You should also consider using TryParse instead of Parse so that you can handle user input errors gracefully. Here's the solution sticking with Parse:
public decimal AveragePercentage()
{
decimal sum = decimal.Parse(tbEnglish.Text) +
decimal.Parse(tbUrdu.Text) +
decimal.Parse(tbPhysics.Text) +
decimal.Parse(tbChemistry.Text) +
decimal.Parse(tbMaths.Text);
return sum / 5m;
}
Out of interest, in your original code why are you dividing by 500 and then multiplying by 100? Why not just divide by 5 (as mine does now that I've noticed what was going on)?
As a side note, it's very important to differentiate between compile-time errors and execution-time errors. It wasn't the compiler saying that the input string wasn't in the correct format - it was the Convert.ToDouble method, at execution time. In this case it was relatively obvious, but in other situations we could have been chasing our tails for a while trying to find a compile-time problem when it was actually failing at execution time.
I don't have Visual Studio available to me here on my Linux box, but I think you're better off with code like this.
private double per()
{
double a = Convert.ToDouble(tbEnglish.Text);
a += Convert.ToDouble(tbPhysics.Text);
a += Convert.ToDouble(tbChemistry.Text);
a += Convert.ToDouble(tbMaths.Text);
double d = 500;
double lblResult = (a / d)*100;
return lblResult;
}
In your example, you end up building a string that will look like: "75.692.156.372.3", which cannot be parsed into a double.
You need to convert all the TextBox.Text values into Decimals before using the + operator.

Comparing double values in C#

I've a double variable called x.
In the code, x gets assigned a value of 0.1 and I check it in an 'if' statement comparing x and 0.1
if (x==0.1)
{
----
}
Unfortunately it does not enter the if statement
Should I use Double or double?
What's the reason behind this? Can you suggest a solution for this?
It's a standard problem due to how the computer stores floating point values. Search here for "floating point problem" and you'll find tons of information.
In short – a float/double can't store 0.1 precisely. It will always be a little off.
You can try using the decimal type which stores numbers in decimal notation. Thus 0.1 will be representable precisely.
You wanted to know the reason:
Float/double are stored as binary fractions, not decimal fractions. To illustrate:
12.34 in decimal notation (what we use) means
1 * 101 + 2 * 100 + 3 * 10-1 + 4 * 10-2
The computer stores floating point numbers in the same way, except it uses base 2: 10.01 means
1 * 21 + 0 * 20 + 0 * 2-1 + 1 * 2-2
Now, you probably know that there are some numbers that cannot be represented fully with our decimal notation. For example, 1/3 in decimal notation is 0.3333333…. The same thing happens in binary notation, except that the numbers that cannot be represented precisely are different. Among them is the number 1/10. In binary notation that is 0.000110011001100….
Since the binary notation cannot store it precisely, it is stored in a rounded-off way. Hence your problem.
double and Double are the same (double is an alias for Double) and can be used interchangeably.
The problem with comparing a double with another value is that doubles are approximate values, not exact values. So when you set x to 0.1 it may in reality be stored as 0.100000001 or something like that.
Instead of checking for equality, you should check that the difference is less than a defined minimum difference (tolerance). Something like:
if (Math.Abs(x - 0.1) < 0.0000001)
{
...
}
You need a combination of Math.Abs on X-Y and a value to compare with.
You can use following Extension method approach
public static class DoubleExtensions
{
const double _3 = 0.001;
const double _4 = 0.0001;
const double _5 = 0.00001;
const double _6 = 0.000001;
const double _7 = 0.0000001;
public static bool Equals3DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _3;
}
public static bool Equals4DigitPrecision(this double left, double right)
{
return Math.Abs(left - right) < _4;
}
...
Since you rarely call methods on double except ToString I believe its pretty safe extension.
Then you can compare x and y like
if(x.Equals4DigitPrecision(y))
Comparing floating point number can't always be done precisely because of rounding. To compare
(x == .1)
the computer really compares
(x - .1) vs 0
Result of sybtraction can not always be represeted precisely because of how floating point number are represented on the machine. Therefore you get some nonzero value and the condition evaluates to false.
To overcome this compare
Math.Abs(x- .1) vs some very small threshold ( like 1E-9)
From the documentation:
Precision in Comparisons
The Equals method should be used with caution, because two apparently equivalent values can be unequal due to the differing precision of the two values. The following example reports that the Double value .3333 and the Double returned by dividing 1 by 3 are unequal.
...
Rather than comparing for equality, one recommended technique involves defining an acceptable margin of difference between two values (such as .01% of one of the values). If the absolute value of the difference between the two values is less than or equal to that margin, the difference is likely to be due to differences in precision and, therefore, the values are likely to be equal. The following example uses this technique to compare .33333 and 1/3, the two Double values that the previous code example found to be unequal.
So if you really need a double, you should use the techique described on the documentation.
If you can, change it to a decimal. It' will be slower, but you won't have this type of problem.
Use decimal. It doesn't have this "problem".
Exact comparison of floating point values is know to not always work due to the rounding and internal representation issue.
Try imprecise comparison:
if (x >= 0.099 && x <= 0.101)
{
}
The other alternative is to use the decimal data type.
double (lowercase) is just an alias for System.Double, so they are identical.
For the reason, see Binary floating point and .NET.
In short: a double is not an exact type and a minute difference between "x" and "0.1" will throw it off.
Double (called float in some languages) is fraut with problems due to rounding issues, it's good only if you need approximate values.
The Decimal data type does what you want.
For reference decimal and Decimal are the same in .NET C#, as are the double and Double types, they both refer to the same type (decimal and double are very different though, as you've seen).
Beware that the Decimal data type has some costs associated with it, so use it with caution if you're looking at loops etc.
Official MS help, especially interested "Precision in Comparisons" part in context of the question.
https://learn.microsoft.com/en-us/dotnet/api/system.double.equals
// Initialize two doubles with apparently identical values
double double1 = .333333;
double double2 = (double) 1/3;
// Define the tolerance for variation in their values
double difference = Math.Abs(double1 * .00001);
// Compare the values
// The output to the console indicates that the two values are equal
if (Math.Abs(double1 - double2) <= difference)
Console.WriteLine("double1 and double2 are equal.");
else
Console.WriteLine("double1 and double2 are unequal.");
1) Should i use Double or double???
Double and double is the same thing. double is just a C# keyword working as alias for the class System.Double
The most common thing is to use the aliases! The same for string (System.String), int(System.Int32)
Also see Built-In Types Table (C# Reference)
Taking a tip from the Java code base, try using .CompareTo and test for the zero comparison. This assumes the .CompareTo function takes in to account floating point equality in an accurate manner. For instance,
System.Math.PI.CompareTo(System.Math.PI) == 0
This predicate should return true.
// number of digits to be compared
public int n = 12
// n+1 because b/a tends to 1 with n leading digits
public double MyEpsilon { get; } = Math.Pow(10, -(n+1));
public bool IsEqual(double a, double b)
{
// Avoiding division by zero
if (Math.Abs(a)<= double.Epsilon || Math.Abs(b) <= double.Epsilon)
return Math.Abs(a - b) <= double.Epsilon;
// Comparison
return Math.Abs(1.0 - a / b) <= MyEpsilon;
}
Explanation
The main comparison function done using division a/b which should go toward 1. But why division? it simply puts one number as reference defines the second one. For example
a = 0.00000012345
b = 0.00000012346
a/b = 0.999919002
b/a = 1.000081004
(a/b)-1 = 8.099789405475458e-5‬
1-(b/a) = 8.100445524503848e-5‬
or
a=12345*10^8
b=12346*10^8
a/b = 0.999919002
b/a = 1.000081004
(a/b)-1 = 8.099789405475458e-5‬
1-(b/a) = 8.100445524503848e-5‬
by division we get rid of trailing or leading zeros (or relatively small numbers) that pollute our judgement of number precision. In the example, the comparison is of order 10^-5, and we have 4 number accuracy, because of that in the beginning code I wrote comparison with 10^(n+1) where n is number accuracy.
Adding onto Valentin Kuzub's answer above:
we could use a single method that supports providing nth precision number:
public static bool EqualsNthDigitPrecision(this double value, double compareTo, int precisionPoint) =>
Math.Abs(value - compareTo) < Math.Pow(10, -Math.Abs(precisionPoint));
Note: This method is built for simplicity without added bulk and not with performance in mind.
As a general rule:
Double representation is good enough in most cases but can miserably fail in some situations. Use decimal values if you need complete precision (as in financial applications).
Most problems with doubles doesn't come from direct comparison, it use to be a result of the accumulation of several math operations which exponentially disturb the value due to rounding and fractional errors (especially with multiplications and divisions).
Check your logic, if the code is:
x = 0.1
if (x == 0.1)
it should not fail, it's to simple to fail, if X value is calculated by more complex means or operations it's quite possible the ToString method used by the debugger is using an smart rounding, maybe you can do the same (if that's too risky go back to using decimal):
if (x.ToString() == "0.1")
Floating point number representations are notoriously inaccurate because of the way floats are stored internally. E.g. x may actually be 0.0999999999 or 0.100000001 and your condition will fail. If you want to determine if floats are equal you need to specify whether they're equal to within a certain tolerance.
I.e.:
if(Math.Abs(x - 0.1) < tol) {
// Do something
}
My extensions method for double comparison:
public static bool IsEqual(this double value1, double value2, int precision = 2)
{
var dif = Math.Abs(Math.Round(value1, precision) - Math.Round(value2, precision));
while (precision > 0)
{
dif *= 10;
precision--;
}
return dif < 1;
}
To compare floating point, double or float types, use the specific method of CSharp:
if (double1.CompareTo(double2) > 0)
{
// double1 is greater than double2
}
if (double1.CompareTo(double2) < 0)
{
// double1 is less than double2
}
if (double1.CompareTo(double2) == 0)
{
// double1 equals double2
}
https://learn.microsoft.com/en-us/dotnet/api/system.double.compareto?view=netcore-3.1

Categories

Resources