TheMasterSoda
TheMasterSoda

Reputation: 3

Converting string to double correctly

I am writing a program in c# and have encountered an annoying little problem. I need to convert fields from dataGridView control to double in order to store them in database. However, it doesn't convert correctly.

The original values in dataGridView use comma (,) for decimal point separation.

Here's the original code:

double number = Convert.ToDouble(dataGridView1.Rows[row].Cells[1].Value)

The cell is textbox type. By using this method 12,3 becomes 12,3E+14

For some unknown reasons, the converter multiplies the number by 10 with the power 14.

After reading some questions, I stumbled upon another possible solution

double number = Convert.ToDouble(dataGridView1.Rows[row].Cells[1].Value, CultureInfo.CurrentCulture);

Still the same result. 12,3 -> 12,3E+14

double number = Convert.ToDouble(dataGridView1.Rows[row].Cells[1].Value.ToString(), CultureInfo.CurrentCulture);

This gets even more interesting. Instead of 12,3 i'm getting 123

Am I missing something? Is there a simple solution to all of this?

EDIT: just in case - the database field type is set to real and dataGridView cell is TextBox type, so the input is string type.

EDIT2: The thing I am trying to do is to load value (real) from database to DGV, save it to a different database table as real, then load the value from the newly written database table (real) and show it in another DGV. After writing the values from DGV1 to database, their type is Single. After writing them to database the 2nd time, however, the value becomes String type, even though i did no changes to it. Could this be what's distorting the conversion values? I mean the 1st time they show up as 12,3E+14 instead of 12,3. I could just divide them by Math.Pow(10, 14) to get the original value, but this is dirty practice :/

FINAL EDIT: Thank you all for your help, but the real problem in this case was my carelessness. As this program is being developed for quite a while, back when I was still getting used to c# syntax, I have included some variable type mix-ups, which has led me to having to review all the types in the code. Again, thank you all for help.

TL;DR - keep your variable types consistent.

Upvotes: 0

Views: 3454

Answers (6)

TheMasterSoda
TheMasterSoda

Reputation: 3

I have finally solved my problem. It appears, that even though C# has localization options, SQL doesn't.

Numbers were converting just fine, but SQL parsed queries wrong:

"INSERT INTO myTable VALUES ('2,5' , '3,1'); 

didn't work, but this did:

"INSERT INTO myTable VALUES ('2.5' , '3.1');

Upvotes: 0

Ric Gaudet
Ric Gaudet

Reputation: 918

If your CurrentCulture is, say, in the US, it will parse "1,23" as 123.

As Tigran noted, create a FormatProvider, or create a NumberFormatInfo. Here is an alternate solution, if you don't want/need to change the CurrentCulture defaults.

NumberFormatInfo provider = new NumberFormatInfo();
provider.NumberDecimalSeparator = ",";
double num = Convert.ToDouble("1,23", provider);

If this line of code gives you 123:

double number = Convert.ToDouble(dataGridView1.Rows[row].Cells[1].Value.ToString(), CultureInfo.CurrentCulture);

then this should give you 1.23:

NumberFormatInfo provider = new NumberFormatInfo();
provider.NumberDecimalSeparator = ",";
double number = Convert.ToDouble(dataGridView1.Rows[row]
.Cells[1].Value.ToString(),provider);

Upvotes: 2

Tigran
Tigran

Reputation: 62265

The first and second cases are identical, cause in both cases function uses CurrentCulture like a second parameter.

The third one is more interesting as you use: Convert.ToDouble(String) overload, which uses

the formatting conventions of the current thread culture.

which may defer from that one of your machine and else.

So like the first thing to do, imo, you can check if the current debugging (I immagine) thread culture is equal to that one of your machine, if not that makes a difference.

Consider that in "fr-FR" the decimal separator is "," where in "en-US" is ".". In order to correctly threat the known format of the data you get you need to provide custom FormatProvider and parse using it.

So in your case the code may look like:

 //assign expected separator
 NumberFormatInfo nf = new NumberFormatInfo();
 nf.NumberDecimalSeparator = ",";

 var val = dataGridView1.Rows[row].Cells[1].Value;
 double number = Convert.ToDouble(val, nf);

Should work for you.

Upvotes: 0

Olivier Jacot-Descombes
Olivier Jacot-Descombes

Reputation: 112762

Since the Value property is of type object, it could contain a boxed double value already. In that case a cast would be sufficient:

double number = (double)dataGridView1.Rows[row].Cells[1].Value;

or, if the column is nullable, possibly

double? number = (double?)dataGridView1.Rows[row].Cells[1].Value;

Note that this does not involve a conversion, it just casts the value to its right type.

Try to output this in order to know the type of the value:

System.Diagnostics.Debug.WriteLine(
    dataGridView1.Rows[row].Cells[1].Value.GetType().Name);

And open the ouput window.

Upvotes: 0

Jeff Musser
Jeff Musser

Reputation: 121

you could try calling the replace function on the string to replace , with a . then doing the conversion. Try this:

double number = Convert.ToDouble(dataGridView1.Rows[row].Cells[1].Value.ToString().Replace(",", "."));

Upvotes: 0

Praveen Shakkarval
Praveen Shakkarval

Reputation: 56

Have you try

double da = double.Parse(a, CultureInfo.InvariantCulture);

Here in similar kind of problem

they used it

C# convert string to double in locale

Upvotes: 0

Related Questions