Force .Net program to use '.' as decimal symbol - c#

I'm trying to get a string formatted float number (e.g. "3.14") from a COM port.
I used Convert.ToSingle() but it threw exception "Input string was not in a correct format" And while debugging, I found that double, float and decimal numbers are separated by '/' instead of '.'; for example 3.14 was 3/14.
My system language is English, but date and time formats are in Persian (Windows 10). In Persian, we use / instead of . as the decimal symbol.(۳/۱۴ = 3.14)
Is there any way to make program independent of system regional settings and force it to always use '.' as decimal symbol?

Using Convert.ToSingle will attempt to convert an object to a floating-point number based on the system's region settings, as you have already noticed.
In order to reliably convert a string that is, for example, in US-English format, you can provide an additional argument of the type IFormatProvider to the method.
string text = "3.5";
IFormatProvider culture = System.Globalization.CultureInfo.GetCultureInfo("en-US");
float number = Convert.ToSingle(text, culture);
The result stored in number be 3.5, i.e. the number halfway between three and four, independent of your system settings. For example, the above code works as expected on my computer, even though it's set to the German (de-DE) region, which represents the same number as 3,5.
See also the documentation of Convert.ToSingle for details.

Related

How to fix a different decimal setting on a second computer C#

So as I've stated in my question I recently wrote a small program to calculate the amount of bricks needed to build a room, using the following
float result = ((fLenght * fWitdh) * fHeight) * bricksPerMeter;
When Running a test case on both my main computer and a second computer they come up with a different answer
Ex: PC 1 ((15 * 1)* 1.8)* 40 = 1080
PC 2 with the same values produces 600 as the answer
now the error is fixed by changing the decimal symbol on the second computer
I want to know if there is anyway for my code to check if this is the case and attempt to fix it
without me going to each computer and setting it manually
Normally when you launch a .NET application, it takes its default culture settings from the operating system. That is to say that computer configured for German (Germany) would result in the de-de culture being used in the application, and a computer configured for English (United Kingdom) would result in the en-gb culture being used in the application.
With these cultures come things like date format strings, decimal separators, etc. which is where your issue comes from.
A simple solution is to change your code, which is currently:
float.TryParse(value, out fValue) ? fValue : 1f
to use the Invariant Culture:
float.TryParse(value, NumberStyles.Any, CultureInfo.InvariantCulture, out fValue) ? fValue : 1f;
This will then use the invariant culture, whose decimal separator is ., to parse the string to a float.
Note that you'll probably want to enforce a culture when you convert the result back to a string. One way to do this is by passing a culture to the .ToString method:
string resultText = result.ToString(CultureInfo.InvariantCulture);
Console.WriteLine(resultText);
Alternative solution (but not recommended): you could override the default culture for your entire application but that might cause problems for you elsewhere, so I don't recommend this.

How to convert an integer value to a special format

I have a numeric value. I want to format it like this:
input: 500000 $
output: 500.000 $
How do I do that?
You can use custom format strings to handle displaying the number the way you want without having to actually change its value.
As long as that dot character is actually a thousands separator in your culture, you can use the format string ##,# $.
var value = 50000;
Console.WriteLine(value.ToString("##,# $"));
# acts as a numeric place holder,
, acts as the separator (this
particular string can handle larger numbers, the groups are repeated for each "thousand" grouping, see this for more detail on how it works),
$ is displayed
literally.
The output is : 50.000 $ as requested.
Also, because this formatting is culture dependant, it will display correctly if the program happens to be run in a country that uses a different separator.
If 500.000 $ happens to be the "normal" way your culture displays currency, you can use the standard format string C0. This simple formats the number with your culture's default currency format, with 0 decimal places. This will also automatically adjust for the culture of the person running the application.
If you do NOT want these to adjust to the culture format of the user, you can pass an explicit culture to ToString.
var value = 50000;
var culture = new CultureInfo("fr-FR");
Console.WriteLine(value.ToString("C0", culture));
This will display 500 000 € on my machine, even though the default culture (en-US) would cause it to display $50,000
Your question is quite easy to solve and you should be able to do it.
In pseudocode (You are gonna have to write the program):
float num
Writeline input number;
read line num;
num = num / 1000;
print num;

Formatting a String to be Converted to Double

I'm trying to convert a string to double. The incoming string is always going to be a whole number...no decimals. So, for example "90".
double percentToCheck = Convert.ToDouble(String.Format("{0:0.00}", SomeEntity.KeyIDs.SomePercentTrigger));
SomePercentTrigger is the % that I will be converting.
I get a "string is not in the correct format" error so how should I format this string? I've got to format it because if I don't I get the same error with just this during the conversion:
double percentToCheck = Convert.ToDouble(SomeEntity.KeyIDs.SomePercentTrigger);
UPDATED:
SomePercentTrigger is simply a string such as "80"..it'll always be a whole number too.
Update:
Your string is "52.0".
It must be the '.' that causes the FormatException.
You are probably on a machine where '.' is not set as the decimal point (e.g. I live in Germany and use German regional settings. Our decimal point is ',' )
To get around this problem you need to parse the string using CultureInfo.InvariantCulture.
var value = double.Parse(myString, CultureInfo.InvariantCulture);
InvariantCulture should be used for the parts of your application that revolve around data storage. Make sure you use it as well when converting doubles to strings Console.WriteLine(value.ToString(CultureInfo.InvariantCulture));
I suspect that SomeEntity.KeyIDs.SomePercentTrigger has some invalid characters in it (something other than digits, '.' and a optional leading '-'), say for example "80%"
So you're getting a FormatException on this line
double percentToCheck = Convert.ToDouble(String.Format("{0:0.00}", SomeEntity.KeyIDs.SomePercentTrigger));
because {0:0.00} formatting rules are only valid for numeric values.
Also you get the very same exception here:
double percentToCheck = Convert.ToDouble(SomeEntity.KeyIDs.SomePercentTrigger);
because "80%" can not be converted into a double.
You should either
put some logging right in front of the failing statement
or debug that code
and see what the actual content of SomeEntity.KeyIDs.SomePercentTrigger is.
Use double.Parse(string) or alternatively double.TryParse(string, out value)
It doesn't make sense to try to format a string. You would have to parse it to a number first in order to format it. Anyhow, there is no problem in parsing a number without decimals as a double, so the string is probably not containing what you think it does.
If the string contains a number in integer format, parse the string as an integer, and then convert the integer to a double:
double percentToCheck = (double)Int32.Parse(SomeEntity.KeyIDs.SomePercentTrigger);

Why do I get a FormatException when converting a string to a float?

When I try to convert a string to float:
Console.WriteLine(float.Parse("6.59"));
it throws an exception:
Unhandled Exception: System.FormatException: Input string was not in a correct f
ormat.
at System.Number.ParseSingle(String value, NumberStyles options, NumberFormat
Info numfmt)
When I try it like this:
Console.WriteLine(Convert.ToSingle("6.59"));
It throws the same exception:
Unhandled Exception: System.FormatException: Input string was not in a correct f
ormat.
at System.Number.ParseSingle(String value, NumberStyles options, NumberFormat
Info numfmt)
at System.Convert.ToSingle(String value)
Can you explain why this happens?
The single argument Parse method uses the current culture to parse the string. If your current culture uses some other decimal separator, this will fail.
Try using the invariant culture:
float.Parse("6.59", CultureInfo.InvariantCulture)
The problem here is your culture.
Either set the invariant culture like this:
float.Parse("6.59", CultureInfo.InvariantCulture)
or use the correct decimal separator for your culture
float.Parse("6,59")
I wonder why you are using a literal string. If you are having problems entering literal floats, you can use
Console.WriteLine(6.59f)
If you do it this way culture doesn't matter because the value is decided at compile time.
You are probably using a culture that uses the , as a decimal seperator.
You could try to Parse using the InvariantCulture:
float.Parse("6.59", CultureInfo.InvariantCulture)
Culture - specific things. What's your default culture?
Some cultures use "," instead of ".". You can try this:
float.Parse("6.59", CultureInfo.InvariantCulture);
There could be problem with Locale/Culture. You need to set , instead of . for the decimal separator.
I know everyone here has already given the reason for the problem experienced but perhaps somebody should just expand on why Invariant fixes it.
The CultureInfo class is used either directly or indirectly by classes that format, parse, or manipulate culture-specific data, such as String, DateTime, DateTimeOffset, and the numeric types to deal with the differences in the way different cultures write these types.
In case of the decimal type some cultures use a period(.) whilst others use a comma (,). By default when you are using the Conversion Libraries it will make use of your local culture (that is the country your OS to configured for).
By specifying Invariant you say that you expect thousand separators to be commas(,) and decimal deliminator to be a period(.) as it is in most cultures.
A big problem that sometimes happens is that these cultural conventions change from the OS point of view. For example the South African (ZA) culture info used to behave like the invariant culture. Microsoft changed this with Windows 8 where the decimal suddenly became a comma and the thousand separator a space.This resulted in many legacy systems written in .Net suddently breaking when one migrated them to newer operating systems.
In the end, deal normalize all local culture info to invariant and persist and deal with them in your business logic in this format. Then localize it back on the front end. Same goes for DateTime, as soon as possible convert to UTC, and only back when you render an output.
You could also try Convert class to perform this task.
Convert.ToDecimal("6.59");

Defining decimal numbers on different operation system, how to understand if point or comma is used by C#

I have written a small program where the program works differently on different operating systems (xp, win7) The problem is the program reads some float numbers such 2,686.
One operating system (win7) convert it to float true, but on xp it goes wrong and print it 2686. How can I understand which symbol the operation system uses for decimal numbers ?
Thanks.
string sep = CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator;
This does not depend on the operating system but at the (default) language settings on each PC.
If you use : double value = double.Parse(text); you are using whatever culture the user has configured. If you know the input to be in a certain format, use:
var ci = CultureInfo.GetCulture("nl-NL"); // dutch
double value = double.Parse(text, ci);
Every function that converts has (1 or more) overloads to take a FormattingProvider (Culture).
parse the floating point numbers using the user current culture with double.Parse(string, System.Globalization.CultureInfo.CurrentCulture);
The decimal separator is decided by the current culture.
If you want to use a specific character as decimal separator, you can create a custom NumberFormatInfo object with any separator you like. If you want to use period as deimcal separator, you can simply use InvariantCulture:
double n = Double.Parse(s, CultureInfo.InvariantCulture);
If you want to use comma, you can choose a culture that has that, for example swedish:
double n = Double.Parse(s, CultureInfo.GetCultureInfo("sv-SE"));

Categories

Resources