Some test code:
string Input = "13.00"
float Output = float.Parse(Input, new CultureInfo("en-US"));
On my PC (Win10 x64, English - US) the value of output is 13.
On another PC (Win10 x64) that I don't have access to where the language is US English but the region is Denmark, the value of Output is 1300.
I've tried to recreate the settings on my PC by swapping comma and decimal point and setting the system locale to Denmark but it always gives a value of 13 for me.
I've tried it on some German Win10 x64 PCs and they also set Output to 13.
I thought the purpose of specifying the culture was to force the use of the comma and decimal point to a specific usage?
Any ideas what I am doing wrong here? Thanks!
Update
Adding the following code:
string Debug = string.Format("{0:0.00}", Output);
results in Debug containing "13.00" on our test PCs (English and German) and "1300,00" on the problem PC.
Update 2
Changing from new CultureInfo("en-US") to CultureInfo.InvariantCulture seems to get the correct output of 13 on the problem PC.
What is the difference between en-US and invariant and why would that only manifest itself on this one example PC that we have seen so far?
Related
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.
We are seeing what appears to be an anomaly/inconsistency in .NET's DateTime ToString() for US culture, "en-US". On some Windows systems, a four-digit year is displayed and on others, a two-digit year is displayed for the same code and the same culture, en-US.
On our Windows 2016 Servers, the code below displays 10/25/1999, which is what we expect.
On some of our Windows 10 Pro workstations, the following code displays 10/25/1999 but on others, it displays 10/25/99. We have not yet isolated the cause/differences between the boxes. Some boxes are upgraded to Fall Creator's update, some have .NET 4.7.1 installed, one box that displayed 10/25/99 had not been updated for months (we turned it on just to run this test).
The code that demonstrates the issue is:
var date = DateTime.Parse("10/25/1999", CultureInfo.InvariantCulture);
// correctly, always displays 1999
Console.WriteLine(date.Year);
// correctly, always displays 10/25/1999
Console.WriteLine(date.ToString("d", CultureInfo.InvariantCulture));
// **INCONSISTENT--displays 10/25/1999 on some boxes and 10/25/99 on others**
Console.WriteLine(date.ToString("d", new CultureInfo("en-US")));
// **INCONSISTENT--displays 10/25/1999 12:00:00 AM on some boxes and 10/25/99 12:00:00 AM on others**
Console.WriteLine(date.ToString(new CultureInfo("en-US")));
// Force formatting--correctly, always displays 10/25/1999
Console.WriteLine(date.ToString("MM/dd/yyyy", new CultureInfo("en-US")));
We have tested against .NET Frameworks ranging from v2 to v4.7.1 and in both x64 and x86 modes. Varying these does not change the number of digits displayed. It seems almost as though the number of digits displayed for the en-US culture is configured based on some OS setting.
I'm probably missing something obvious. Thank you for your help and insights.
p.s. I looked at threads like Strange behaviour of DateTime.Parse but that doesn't seem to be the issue since the issue we are seeing is in ToString. Parsing works fine.
From MSDN:
The user might choose to override some of the values associated with
the current culture of Windows through the regional and language
options portion of Control Panel. For example, the user might choose
to display the date in a different format or to use a currency other
than the default for the culture. If the culture identifier associated
with name matches the culture identifier of the current Windows
culture, this constructor creates a CultureInfo object that uses those
overrides, including user settings for the properties of the
DateTimeFormatInfo instance returned by the DateTimeFormat property,
and the properties of the NumberFormatInfo instance returned by the
NumberFormat property. If the user settings are incompatible with the
culture associated with the CultureInfo, for example, if the selected
calendar is not one of the OptionalCalendars, the results of the
methods and the values of the properties are undefined.
So my guess is you would like to use the following constructor:
public CultureInfo(string name, bool useUserOverride)
and set useUserOverride to false.
I'm using the Parse method to convert a string to a DateTime object:
requestRecord.TerminationDate = DateTime.Parse(reader.ReadString("Termination_Date"));
This code works on one machine but throws an exception on the other. I think the issue may perhaps be to do with the local culture. Looking at the taskbars on the two machines the one that throws the exception has the date as 01/12/2014 whereas the other shows 12/01/2014.
Is there some way that I can rewrite the above code so that it works on both machines regardless of the local DateTime culture?
I guess the culture settings differ on both machines. Try to supply the format. That explains why the date format is interpreted differently on both machines:
requestRecord.TerminationDate = DateTime.ParseExact
( reader.ReadString("Termination_Date")
, "dd/MM/yyyy"
, CultureInfo.InvariantCulture
);
In this way, you are not depending on the machine and it's settings, but on the format you know.
Depending on what reader is, you might want to use reader.GetDateTime, which does all this for you already, for example SqlDataReader.GetDateTime.
My website extracts data from a text-file into a database. After reading the data, I convert string-values into double, using:
oracom.Parameters.Add("nstpreisvm", OracleDbType.Double).Value = Convert.ToDouble(_material.Mat_StPreisVm);
If I check the results in the database now, (The column expects the NUMBER-format), I get two different values: On my localhost via Visual Studio 2010, the database returns 10,15 - But if I make the process on the webserver, the database only shows 10. How does this happen?
I implemented a little lable on the website now, filling it with the current culture on the Page-Load:
label.Text = Thread.CurrentThread.CurrentCulture.ToString();
The CurrentCulture is en-GB for both instances, so what is the problem here? Am I missing anything?
My local windows is Win7 SP1 with a german language-pack, the server is Win2008 R2 with standard English installation.
We had a similar problem on a customer server where the customer had manually changed the decimal separator symbol for a particular culture on that server. You can check this using:
Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator
I would suggest explicitly specifying the decimal separator symbol when you do the parsing:
Double.Parse("1,25", new NumberFormatInfo(){ NumberDecimalSeparator = "," });
I have a problem with converting string to double, it works fine when I run it on my local machine but when I deploy it to the server it "cuts" 0 in front.
For example I have a string value of 0,0123 and when I convert it to double I get 123.
I use ASP.NET with C#, method I use is Convert.ToDouble() and the hosting is somee.com.
Right now I just divide the number by 10000 and get what I need, but as you can imagine it's not prefect solution so maybe someone has better idea of how to solve it.
This happens because your machine and the server are using two different cultures.
Some cultures use "." as a decimal point, while others use ",".
It seems that in your server culture, "." is the decimal point - and so the comma in "0,0123" is treated as a thousands separator instead.
I would use the overload for double.TryParse or Convert.ToDouble that takes an IFormatProvider and pass in the correct CultureInfo.
In the future, try using CultureInfo.InvariantCulture to format all your internal data (i.e. data persistence, or data flowing within your system), and use the proper CultureInfo for displaying data to the user.
The decimal point is not the same across cultures and, therefore, computers with different culture setting.
Try using double.Parse(string, CultureInfo) with an explicit CultureInfo that works for your format.
Based on the fact you express your value as 0,0123 rather than 0.0123, I would guess the language/culture settings on the server are different than on your own machine.
Try printing out the result of System.Globalization.CultureInfo.CurrentCulture.Name from somewhere on the server, and compare it to what your local machine produces.