Decimal, Float, Double, Help?

  • Thread starter Thread starter Cralis
  • Start date Start date
C

Cralis

Guys,

I have written a small application which accepts GPS coordinated from
a device, and then I build up a GoogleEarth KML file. That's all
done...

And it works for me in Australia.

But a user says it's not working for him, and he's in Turkey, I think.

I got his file, and this is what it SHOULD look like:
(Lat/Long/Alt)

24.988607,44.982925,341.7
24.988594,44.982937,341.4
24.988594,44.982941,341.4
24.988600,44.982941,341.4
24.988602,44.982944,341.5

But this is what it actually looks like after he has parsed it on his
macgine:

2,498861E+07,4,498292E+07,3417
2,498859E+07,4,498294E+07,3414
2,498859E+07,4,498294E+07,3414
2,49886E+07,4,498294E+07,3414
2,49886E+07,4,498294E+07,3415

And fair enough, GoogleEarth doesn't like it.

I am making use of Doubles and Floats to store data... but now I am
thinking that's the issue.

When I output the coordinates to the XML file, I am doing this:

coordinatesElement.InnerText += string.Format("{0},{1},{2}\r\n",
ls.Latitude, ls.Longitude, ls.Altitude);

(All those field types are Doubles)

Hope someone can help!
 
Thanks guys...

I think it's my display that is breaking now... I think internally,
all is OK...

If I have a number as 1.234567... what 'string.format()' should I use
to make it NOT display with the E+07 stuff?
 
Thanks guys.

The Culture thing seems to be helpful.

I can at least reproduce what is happening in Europe now... but doing
this:

Thread.CurrentThread.CurrentCulture = new CultureInfo("de-AT", false);

And now, indeed, my numbers are all being messed up quite a bit.

But I am still unsure of the best way to solve this. The input from
the device is not changable, and comes in as comma separated fields.
for example:

24.988607,44.982925,341.7

I then split that into fields:
24.988607
44.982925
341.7

I then do a tryparse into a Decimal. And that's where it goes wrong.

decimal.TryParse(input, out dec);

So, what I can do is, create a method which takes in the string (This
is for numeric strings only)... checks the cultures
NumberDecimalSeparator. If it's a comma (What I am NOT expecting),
then replace any points, with a comma. So, something like this:

private string GlobaliseString(string input)
{
if
(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator ==
",")
input = input.Replace('.', ',');

return input;
}

I can then do:

string input = "-151.125665331012345";

decimal.TryParse( GlobaliseString(input), out dec);

And that would give me a decimal with the right value. After that
point, I don't worry about commas and decimal points.

I can even set my numericupdown controls with the decimal, and it will
work...

My worry now is... when I export the data to the XML file, it expects
a US style decimal point...

So, I guess when I write the file, I need to have another method, that
checks the culture again, if and the cultures separator is a comma, I
need to do something like:

private string UnGlobaliseString(decimal input)
{
if
(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator ==
",")
{
return input.ToString().Replace(',', '.');
}
return input.ToString();
}

That seems very manual, but does that seem OK?
 
By the way, I am the original posted... Cralis (Cra-Lis).... but the I
seem to ahve two accounts. :(
 
But I am still unsure of the best way to solve this. The input from
the device is not changable, and comes in as comma separated fields.
for example:

24.988607,44.982925,341.7

I then split that into fields:
24.988607
44.982925
341.7

I then do a tryparse into a Decimal. And that's where it goes wrong.

decimal.TryParse(input, out dec);

So, what I can do is, create a method which takes in the string (This
is for numeric strings only)... checks the cultures
NumberDecimalSeparator. If it's a comma (What I am NOT expecting),
then replace any points, with a comma. So, something like this:

private string GlobaliseString(string input)
{
if
(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator ==
",")
input = input.Replace('.', ',');

return input;
}

I can then do:

string input = "-151.125665331012345";

decimal.TryParse( GlobaliseString(input), out dec);

And that would give me a decimal with the right value. After that
point, I don't worry about commas and decimal points.

I can even set my numericupdown controls with the decimal, and it will
work...

My worry now is... when I export the data to the XML file, it expects
a US style decimal point...

So, I guess when I write the file, I need to have another method, that
checks the culture again, if and the cultures separator is a comma, I
need to do something like:

private string UnGlobaliseString(decimal input)
{
if
(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator ==
",")
{
return input.ToString().Replace(',', '.');
}
return input.ToString();
}

That seems very manual, but does that seem OK?

First you decide on what strategy to use:
A) same format of data no matter what culture
B) use different format of data depending on culture

If #A then you just write and read with a fixed culture.

If #B then you write and read with the local culture.

You should never need to use Replace.

Arne
 
Thanks guys. Sorry, I'm a bit slow at clicking here.

Data from device which supplies data is in en-US format consists of
Text fields and decimal fields (Both normal values and GPS Co-
ordinates). So, the input is in en-US.

Output is to an XML (kml, actually) file for Google Earth, which
accepts en-US. Another output is to a 'Settings Backup file', which is
XML, and is basically a file containing all the data held in the
application. To keep things simple, that would be en-US formatted as
well.

So the only issue now is how I handle the input, and output.

Arne - with regards the 2 options you mention above, it looks like A
is the strategy. I must always read, and write in en-US format. How
the numbers are dealt with internally is the issue.

So.. my user is in Germany, and reads the deta.
The device gives the data as 12.578

This gets read into a string, say strReply.

I then check it and set it to my decimal value, say decValue, like
this:

if (!Decimal.TryParse(strReply, out decValue)
{
... Explain to the user that there has been an issue.
}

That parses OK, but the value in decValue is wrong because of the
'point' not being a 'comma'. So the value is wrong.

Can you tell me how I SHOULD be reading this in?

Then, the output.
Once I have done some things... I have my decValue which is a decimal.
Assuming I somehow read it in correctly, the VALUE to me is 12.578. On
the German machine, this is being handled as 12,578.

When I output it, I dop something like:

string.Format("<VALUE>{0}</VALUE>", decValue);

This outputs "<VALUE>12,478</VALUE>"

But I need it to output

This outputs "<VALUE>12.478</VALUE>"

How should I be exporting the data? As mentioned above, it looks like
I need to use CultureInfo.InvariantCulture - but not sure how this is
achieved when reading, and writing.

(Again, sorry for not understanding all the effort you have put in
above..)
 
WAIT!!!

I think I just clicked!!!!

I just wrote this.. and it SEEMS to work...
I'm not understanding though. Does
'CultureInfo.InvariantCulture.NumberFormat' always used a point (.) as
the decimal point, or is that related to the users regional settings?
If it ALWAYS uses a point... then it looks like my issues are solved.

Does this seem right?

I'm basically forcing my machine to use de-AT (German) as it's
region...
And my numericUpDown1 is showing the value as "-151,125", even though
my string input is "-151.125".

Can you see if my logic is OK?

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private string sep;
private NumberFormatInfo n;

public Form1()
{
InitializeComponent();
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-
AT", false);

n = CultureInfo.InvariantCulture.NumberFormat;
string a = 5.ToString(n);

}

private void Form1_Load(object sender, EventArgs e)
{
Console.WriteLine("CurrentCulture is {0}.",
CultureInfo.CurrentCulture.Name);
string input = GlobaliseString("-151.125665331012345");

float flt;
double dbl;
decimal dec;

float.TryParse(input, out flt);
double.TryParse(input, out dbl);
decimal.TryParse(input, out dec);

numericUpDown1.Minimum = -1000;

label1.Text = "Dec: " + dec.ToString(n);
label2.Text = "Dbl: " + dbl.ToString(n);
label3.Text = "Flt: " + flt.ToString(n);

numericUpDown1.Value = dec;

}

private string GlobaliseString(string input)
{
if
(CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator ==
",")
input = input.Replace('.', ',');

return input;
}

private void numericUpDown1_KeyDown(object sender,
KeyEventArgs e)
{

}

private void button1_Click(object sender, EventArgs e)
{
label4.Text = numericUpDown1.Value.ToString(n);
}


}
}
 
Thanks Peter.

So, in a German PC... I read the value from the device, which comes in
as a string, in the format, "23.150".

How do I read that into my float variable?

float MyFloat = float.parse(inpurtString,
CultureInfo.InvariantCulture.NumberFormat) ?
 
Thanks Pete.

Sorry, I missed the part about dropping the last bit. Done that now.

And I have run face first into another issue now... :( Kinda
unrelated... but based on a poor design call early on.

I have an object:

class myParameter
{
public string Name {get; set;}
public int ParameterType {get; set;}
public object value {get; set;}

}

What I am currently doing, and probably wrongly so, is storing my
value as an object. The value is determined by the value type. Value
types are String, GPSCoord, Float, Int.. and efw others.

Instead of object, is there a better way to do what I am doing? I'm
thinking Generics, but not sure how this can be done.

So, when I create my object, I do:

myParameter param1 = new myParameter();
param.Name = "Something";
param.ParameterType = 1; // I actually use an enum...
param.value = 5.7;

myParameter param2 = new myParameter();
param2.Name = "Something Else";
param2.ParameterType = 2; // I actually use an enum...
param2.value = "Test String";

Using Parse on an object.. doesn't allow the Culture parameter.

That is, I can't say string myString = float.Parse(myObject,
CultureInfo.InvariantCulture);
 
Back
Top