input string is not in a correct format - c#

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.

Related

Can casting cause minute discrepancies in value?

I'm currently writing the Change Return Program on The Big List of Projects and I encountered a logic error in my code. Here is the snippet in question:
if(change / 1 >= 1) // checks if when divided the value is higher than 1, signaling that there is at least a dollar in change
{
double temp1 = change % 1; // declared as double for casting
temp1 = change - temp1; // and used to remove excess, non-dollar value
dollarNum = (int) temp1;
change -= (double)dollarNum;
}
Where change is a double that before this has a value of 10.01. However, after this snippet runs, the value becomes 0.00999999999999979, rather than 0.01 as I want it. Am I assuming something is wrong with casting here? Or is it something else entirely?
Also, note that I tried reformatting the last line to "change = change - dollarNum and tried swapping out dollarNum with temp1 to avoid casting in that line, but neither fixed the issue.
If I formatted anything wrong please let me know and I'll surely fix it as soon as I can.
A double is not suitable for this kind of calculation because it does not store the value exactly (internally it uses binary fractions instead of decimal ones).
Use 'the 'decimal' type instead (https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/keywords/decimal):
decimal change = 10.1M;
if(change / 1 >= 1) //checks if when divided the value is higher than 1, signalling that there is at least a dollar in change
{
decimal temp1 = change % 1; //declared as double for casting
temp1 = change - temp1; //and used to remove excess, non-dollar value
int dollarNum = (int)temp1;
change -= (decimal)dollarNum;
}

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);

Printing double values

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);

Properly round financial data

I decided to re-create my question:
decimal dTotal = 0m;
foreach (DictionaryEntry item in _totals)
{
if (!string.IsNullOrEmpty(item.Value.ToString()))
{
dTotal += Convert.ToDecimal(item.Value);
}
}
Console.WriteLine(dTotal / 3600m);
Console.WriteLine(decimal.Round(dTotal / 3600m, 2));
Console.WriteLine(decimal.Divide(dTotal, 3600m));
The above code returns:
579.99722222222222222222222222
580.00
579.99722222222222222222222222
So, that is where my issues are coming from, I really need it to just display the 579.99; but any round, be it decimal.Round or Math.Round still return 580; even the string formats for {0:F} return 580.00.
How can i properly do this?
New answer (to new question)
Okay, so you've got a value of 579.99722222222222222222222222 - and you're asking that to be rounded to two decimal places. Isn't 580.00 the natural answer? It's closer to the original value than 579.99 is. It sounds like you essentially want flooring behaviour, but with a given number of digits. For that, you can use:
var floored = Math.Floor(original * 100) / 100;
In this case, you can do both in one step:
var hours = Math.Floor(dTotal / 36) / 100;
... which is equivalent to
var hours = Math.Floor((dTotal / 3600) * 100) / 100;
Original answer (to original question)
Sounds like you've probably got payTotal in an inappropriate form to start with:
using System;
class Test
{
static void Main()
{
decimal pay = 2087975.7m;
decimal time = pay / 3600;
Console.WriteLine(time); // Prints 579.99325
}
}
This is the problem:
var payTotal = 2087975.7;
That's assigning payTotal to a double variable. The value you've actually got is 2087975.69999999995343387126922607421875, which isn't what you wanted. Any time you find yourself casting from double to decimal or vice versa, you should be worried: chances are you've used the wrong type somewhere. Currency values should absolutely be stored in decimal rather than double (and there are various other Stack Overflow questions talking about when to use which).
See my two articles on floating point for more info:
Binary floating point in .NET
Decimal floating point in .NET
(Once you've got correct results, formatting them is a different matter of course, but that shouldn't be too bad...)

Categories

Resources