How to make doubles always contain a . character? - c#

I noticed my doubles contain different precision characters depending on regional settings.
For example:
3,47 or 3.45
How can I enforce the double should always contain a . precision character?
Problem is once I serialize the class containing this double to XML, it gets shipped to other systems expecting a standard result.
So after reading your responses (and thanks), do you guys recommend changing the property to a string, (making the replacements in a string), so that it serializes with the string value (not the double)?

You need to put the double to string using the Invariant Culture.
double d = 3.47;
Console.WriteLine(d.ToString(CultureInfo.InvariantCulture));

You will need to format with the InvariantCulture.
Note that the "." and "," formatting characters are interpreted according to the culture settings.

This little tutorial will be the answer you need, I expect:
http://www.java2s.com/Tutorial/CSharp/0440__I18N-Internationalization/Parsingnumberswithcultureinvariantparsing.htm
double.Parse(numberString, CultureInfo.InvariantCulture);

The double itself doesn't include a "." or a ",", only the print out of the representation does. You can read up on custom formats here.
[Update according to OP]
I don't know exactly what your design looks like, but it would probably be smart to create a string property on your DTO, which would output the formatted string of your double, and then mark your double property as not serializable.

When you need to do this for all numbers in your current applicaton, you can use the following to set it application-wide (new threads will inherit this setting):
// use this statement to force the default:
Application.CurrentCulture = CultureInfo.InvariantCulture;
string s = myNumber.ToString();
// for one number you have to remember to use:
string s = myNumber.ToString(CultureInfo.InvariantCulture);
Note: by default, your application, whether ASP.NET or WinForms, will use the culture settings of the system it is running on (in ASP.NET, you can set the culture globally in the web.config).

Related

C# float to string separator

I am new to C # and I am currently having problems with the following. In C #, I have a Pi floating point number and I want to convert it to a string using the ToString() method. But the conversion gives a string result with a comma "3,1415". On another machine, the same gives the string result with the dot "3.1415". What is the reason for this and what should I do to get a dotted string result?
EDIT: The problem is, I can't change the code, but I can install and uninstall .Net frameworks, change my OS settings, etc.
Edit: if you can't change the code. Change the language/localization of the system to one which uses dot as decimal separator. In Control Panel or Settings.
You should look at internationalization and localization in the System.Globalization namespace.
The advice here is to use one CultureInfo specific for parsing numbers or writing numbers to string.
var flt = 232.23f;
var str = flt.ToString(CultureInfo.InvariantCulture); //for example, you can use CultureInfo.CurrentCulture
This allows you to keep the ThreadCulture without change it.
But take a look at this link https://learn.microsoft.com/en-us/dotnet/api/system.globalization.cultureinfo?view=net-5.0 .Take your time, is dense.
I would just set the current culture at the entry point of your program.
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture("en-GB");
However I would also check the regional settings and so forth on the machine where the comma separator appears.
It is related with current culture info. You can specify the culture info in ToString method as a parameter like;
var convertedFloat = floatVariable.ToString(new CultureInfo("en-GB"));
Thanks to GSerg, for comment about Windows regional settings. That solves my problem. In the Windows Control panel enter Region and Language. In the Formats tab click Additional Settings and in the Decimal symbol field specify what decimal separator must be used when converting a floating point number to a string.

How to convert sql type double-precision in c#

I have a database access, and one of this field is double-precision.
Normally if i set in the textbox 1.71 or 1,71 the field in database should contain 1.71.
But if i execute query the value of acces'field is 171 !!.
public const string QUERY =
#"UPDATE TBLART
SET TBLART.COST = #cost
WHERE TBLART.CODE= '1'";
var param = new DynamicParameters();
var cost = totalCost.Replace(',', '.'); //totalCost is a textbox
param.Add("cost", Double.Parse(cost), DbType.Double);
gsmconn.Execute(QUERY, param);
What i wrong ? Thanks.
double.Parse will use the current thread's culture by default. I suspect your current culture uses "." as a grouping separator.
Two options:
Continue to use Replace as you are already doing, but then specify CultureInfo.InvariantCulture when parsing
Remove the replacement, and just use the current thread's culture when parsing the original value. This relies on the culture being appropriate for the user, but is probably a better solution when that's the case. (Otherwise someone entering "1,234.56" will get a parse error when they expected a value of "just a bit more than 1234".)
If I remember correctly in windows forms you can bind an double property to a textbox and it will automatically take care of parsing and converting. You should not manually do parsing from string to double.
That problem is already solved fro you by the .NET framework.
Another suggestion, your data access code should not do any parsing. That should be done in some higher layer. But better leave it to the framework.

Make Convert.ToDouble work with different CultureInfos

Whats the best way to make the conversion work when you have:
string a = "10.0123";
string b = "10,0123";
And the cultureinfo is either swedish or english, it needs to work with both.
I tried:
double aSwe = Convert.ToDouble(a, CultureInfo.GetCultureInfo("sv-SE"));
double bSwe = Convert.ToDouble(b, CultureInfo.GetCultureInfo("sv-SE"));
double aInv = Convert.ToDouble(a, CultureInfo.InvariantCulture);
double bInv = Convert.ToDouble(b, CultureInfo.InvariantCulture);
Since '.' is not a valid separator in Swe and ',' is not valid in Eng I dont know how to make it work with both using the same code.
Only solution I come up with is to replace the comma or dot before converting but it feels like there should be better solution?
You shouldn't try to make it work with both without any extra context.
It's like trying to parse "06/05/2010" as a date without any cultural information: it could mean the May 6th or June 5th.
Likewise "1,234" is either a value a bit more than a thousand, or a bit more than one: you need to know the cultural information in order to interpret it unambiguously.
So instead of trying to solve the problem of interpreting something without enough information, I suggest you focus on the problem of getting all the information you need (or changing the way you get your text data to always be in one particular format).

Ignoring country-specific decimal separator

I'm currently doing an app, that needs to be able to work with the US number layout (123,456.78) as well as with the German layout (123.456,78).
Now my approach is to use NumberFormatInfo.InvariantInfo about like this:
temp = temp.ToString(NumberFormatInfo.InvariantInfo);
this works great when for example reading a number from a textbox. When System is set to English format it will take the . as separator, when it's set to German it will use the ,.
So far so good....but here's the problem: I have a device that returns info in the American format, and that won't change (transmitted via RS232). So I receive something like 10.543355E-00.
Now when on German setting the . will be discarded since it's just the group separator
and the number I will end up with is 10543355....which is a lot more :)
I tried with the same technique thinking this would make the whole thing kind of 'cultureless' to be able to process it independently from the system language but it didn't work :)
I hope you can maybe help me here...I'd love to use a way without having to implement the whole culture stuff etc since all I need here is really numbers that get calculated the right way.
You should use CultureInfo.InvariantCulture when parsing strings from the device. This will cause it to use the invariant culture, which has the US rules for decimal separation.
Edit in response to comments:
The issue is not when you call .ToString(), but rather when you read the string from the device, and convert it to a number:
string inputFromRS232Device = GetDeviceInput();
double value;
// You need this when converting to the double - not when calling ToString()
bool success = double.TryParse(
inputFromRS232Device,
NumberStyles.Float,
CultureInfo.InvariantCulture,
out value);

How to prohibit comma as decimal separator

I'm writing code with german culture settings
Nevertheless I would like to force the user to use the point as a decimal separator.
My piece of test code outputs the wrong value.
How do I detect the "wrong" comma ?(throw an exception)
string nok_str = "14,9";
string ok_str = "14.9";
double nok_Var1 = double.Parse(nok_str, CultureInfo.InvariantCulture.NumberFormat); // outputs 149.0
double nok_Var2 =Convert.ToDouble(nok_str, CultureInfo.InvariantCulture.NumberFormat); // outputs 149.0
First off, and please forgive me, Iā€™d like to question your design decision:
How is this enhancing the user experience? The application should rather try to accept all unambiguous user input, not reject theoretically sound input.
That said, a number such as ā€œ19,2ā€ will be interpreted, with an invariant culture, as having a thousands separator (which is simply discarded). This is why your code silently produces bad values. If you want to explicitly forbid this input, the easiest way to achieve this is an explicit test:
if (nok_str.Contains(","))
throw new FormatException(ā€¦);
As an alternative, you can try modifying the NumberFormatInfo.NumberGroupSeparator property of a custom NumberFormatInfo object that you pass to the Parse method.
Basically the default is to include AllowThousands in the number style. If you specify the number style you want, you can prohibit this:
using System;
using System.Globalization;
class Test
{
static void Main(string[] args)
{
string text = "19,2";
double value;
bool valid = double.TryParse(text, NumberStyles.Float,
CultureInfo.InvariantCulture,
out value);
Console.WriteLine(valid); // Prints false
}
}
Note that NumberStyles.Float is a composite style for AllowLeadingWhite, AllowTrailingWhite, AllowLeadingSign, AllowDecimalPoint, and AllowExponent - but not AllowThousands.
I am not sure what is the source of your input.
If it comes from user it also depends... If it is GUI application, you may think of restricting the input to certain possible keys, excluding comma. If it is a console app, you can try regular expressions to pre-validate input strings.
If it comes from various sources (i.e. web service) maybe simply brute-force string replace will do the trick?
Last, but not least: there are reasons for parsing to be culture-sensitive and if I were you, I would encourage users to enter valid regional number format instead forcing them to provide incorrect one.

Categories

Resources