string to double parsing error - c#

i have the following code:
static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("mk-MK");
string s2 = "4.434,00";
double d;
if (Double.TryParse(s2, NumberStyles.Number, CultureInfo.CurrentCulture, out d))
{
//String.Format("{0:0.0,00}", d);
Console.WriteLine(d + " Type of: " + d.GetType());
}
else
{
Console.WriteLine("ne go parsirashe");
}
String.Format("{0:0.0,00}", d);
Console.WriteLine(d);
//Console.WriteLine(String.Format("{0:0,0.00}", d));
//Console.WriteLine(s2.GetType().ToString());
//Console.ReadLine();
//String.Format("{0:0.0,00}"
Console.ReadLine();
The output is: 4434 Type of: System.Double
4434
Why isn't the value of d in the format of : 4.434,00 ? Can you please help me with this? I've sent couple of hours trying to figure this out before trying to reach out to you guys. Thanks!!!

You are discarding your formatted string - you are not assigning it to a string and simply outputting the double to the console (which would call ToString() on it).
Try this:
string forDisplay = string.Format("{0:0.0,00}", d);
Console.WriteLine(forDisplay);
Or, even shorter:
Console.WriteLine(string.Format("{0:0.0,00}", d));
Update:
In order to format the string according to your culture, you will need to use the Format overload that takes an IFormatProvider (i.e. a culture) and ensure that the format string uses the right characters for the different parts (, for standard thousands separator and . for standard decimal separator - see here for the meanings of each such character in a format string):
var res = String.Format(CultureInfo.CurrentCulture, "{0:0,0.00}", d);
Console.WriteLine(forDisplay);
Result:
4.434,00

You meant to do:
string formatted = String.Format("{0:0.0,00}", d);
Console.WriteLine(formatted);
string.Format returns a string -- it cannot affect the formatting of a double, since doubles have no formatting at all. Doubles only store the raw numeric value (as bits, internally).

You have the . and , around the wrong way, if I'm understanding what you're trying to do.
If you read the Custom Numeric Format Strings page on MSDN, you can see that you need to use , for the thousands separator, and . for the decimal separator, and (the important part) the target culture is irrelevant here. The format is always the same, regardless of the current culture.
So what you want to use is:
Console.WriteLine("{0:0,0.00}", d);
Then the output is:
4434 Type of: System.Double
4.434,00

Related

Would there be a better way of doing this?

post.Min.ToString("0.00").Replace(",", ".").Replace(".00", string.Empty)
post.Min is a double such as 12,34 or 12,00. Expected output is 12.34 or 12.
I basically want to replace the comma by a point, and cut the .00 part if any.
I am asking because I couldn't find anything, or because I don't exactly know what to search. This has an high change of being a duplicate, I simply can't find it. Please let me know.
The simplest solution would appear to be to use CultureInfo.InvariantCulture, and I reject the suggestion that this is any more complicated than using a series of replaces as you demonstrated in your question.
post.Min.ToString("0.##", CultureInfo.InvariantCulture);
# is the digit placeholder, described as the docs like this:
Replaces the "#" symbol with the corresponding digit if one is present; otherwise, no digit appears in the result string.
Try it online
If you use this in a lot of places, and that's why you want to keep it simple, you could make an extension method:
public static class MyExtensions
{
public static string ToHappyString(this double value)
{
return value.ToString("0.##", CultureInfo.InvariantCulture);
}
}
And then you just have to call .ToHappyString() wherever you use it. For example, post.Min.ToHappyString()
You can use .ToString("0.##").
like,
// Considered german culture; May be this is your current culture
CultureInfo culture = new CultureInfo("de");
double number1 = Double.Parse("12,34", culture);
double number2 = Double.Parse("12,00", culture);
Console.WriteLine(number1.ToString("0.##"));
Console.WriteLine(number2.ToString("0.##"));
Output:
12.34
12
.Net fiddle
Checkout the ToString overloads article on MSDN about examples of the N format. This is also covered in the Standard Numeric Format Strings article.
Relevant examples:
// Formatting of 1054.32179:
// N: 1,054.32
// N0: 1,054
// N1: 1,054.3
// N2: 1,054.32
// N3: 1,054.322
For the dot instead of comma to do it properly, in combination with N0 use:
System.Globalization.CultureInfo customCulture = (System.Globalization.CultureInfo)System.Threading.Thread.CurrentThread.CurrentCulture.Clone();
customCulture.NumberFormat.NumberDecimalSeparator = ".";
System.Threading.Thread.CurrentThread.CurrentCulture = customCulture;
double.ToString("0.##") to consider decimal places only if not .00 and you can create your own Number Format without using Culture:
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ".";
post.Min.ToString("0.##", nfi);

C# - Using NumberFormatInfo with Convert.ToDouble to return double

In my application I have internationalization and so we have a bunch of methods to deal with formatting.
One of them should receive a double and format it to two decimal places and return a double. For doing so, we are using NumberFormatInfo according to the culture selected.
The problem is I cant get Convert.ToDouble to work with NumberFormatInfo the way I would like to. Basically what I want to know is why this:
using System;
using System.Globalization;
public class Program
{
public static void Main()
{
var myDouble = 9.983743;
var nfi = new NumberFormatInfo() {
NumberDecimalDigits = 2
};
Console.WriteLine("Original value: " + myDouble);
Console.WriteLine("Converted value: " + Convert.ToDouble(myDouble, nfi));
}
}
Prints
Original value: 9.983743
Converted value: 9.983743 // Should be 9.98
And how can I get the result I want using NumberFormatInfo only, if possible.
Thanks,
From MSDN:
The NumberDecimalDigits property is used with the "F" and "N" standard format strings without a precision specifier in numeric formatting operations.
The default is the generic formatting (G). So this will give you the desired result:
Console.WriteLine(myDouble.ToString("N", nfi));
However, 2 is the default value anyway. And it is better to specify it explicitly:
Console.WriteLine(myDouble.ToString("N2", NumberFormatInfo.InvariantInfo));
Update:
Yeah but I do need to return a double from my method.
Now I see. In your place I would return the original double in that case, too. If the consumer of your API wants to display/store it as a string with two digits, then it is his responsibility to format it.
If you really want to omit the last digits of the precision and return a modified value, then use Math.Round instead (but I would not recommend that).
Converting a double to a double does not change anything, a double is always double precision, you cannot change the number of decimal digits.
A double has no format, format comes into play when you display a double by using the ToString() method as explained by taffer.
You can round it down to set all digits after the first 2 to zero, but you cannot remove digits.
You state you want to return a double with only 2 digits after the decimal place. Therefore, you are not formatting you are rounding:
Math.Round(myDouble, 2)
9.98

Strange output when converting string to double

I already searched for my problem but I wasn't successfully and that's the reason I'm here.
All I want to do is reading a string like "3.14" and convert it to double.
Enough said... here is my code:
using System;
namespace GlazerCalcApplication
{
class MainClass
{
public static void Main (string[] args)
{
string heightString;
double height;
heightString = Console.ReadLine();
height = Convert.ToDouble(heightString);
Console.WriteLine(height);
}
}
}
Output:
3.14
314
Press any key to continue...
Why is my double value not 3.14?
Instead of Convert.ToDouble() I also tried it with double.Parse() but I received the same behaviour. Reading strings like 3,14 is no problem.
Maybe I should also mention that I use MonoDevelop and a linux OS.
Thanks in advance.
Try specifying the culture as Invariant:
height = Convert.ToDouble(heightString,CultureInfo.InvariantCulture);
It seems the decimal seperator of your culture is comma instead of dot therefore dot is truncated after conversion.
Convert.ToDouble(string) uses Double.Parse(string, CultureInfo.CurrentCulture) method explicitly.
Here how it's implemented;
public static double ToDouble(String value) {
if (value == null)
return 0;
return Double.Parse(value, CultureInfo.CurrentCulture);
}
It is likely your CurrentCulture's NumberFormatInfo.NumberDecimalSeparator property is not . (dot). That's why you can't parse a string with . as a date seperator.
Example in LINQPad;
CultureInfo c = new CultureInfo("de-DE");
c.NumberFormat.NumberDecimalSeparator.Dump(); // Prints ,
As a solution, you can create a new reference of your CurrentCulture and assing it's NumberDecimalSeparator property to . like;
double height;
CultureInfo c = new CultureInfo("de-DE");
c.NumberFormat.NumberDecimalSeparator = ".";
height = Convert.ToDouble("3.14", c);
Judging by the result I take it you are in a culture zone where comma is the normal decimal separator.
Also, I take it that you want both dot and comma to be used for decimal separation.
If not, the below is not the proper solution.
The fastest solution for using both would be
height = Convert.ToDouble(heightString.Replace('.', ',');
This would mean that both dots and comma's are used as comma and thus parsed as a decimal separator.
If you only want to use a dot as separator, you can use invariantculture or a specific numberformatinfo. Invariant culture is already shown in the other posts. numberformat info example:
var nfi = new NumberFormatInfo { NumberDecimalSeparator = "." };
height = double.Parse(heightString,nfi);
For completeness, the example below shows both using numberformatinfo for setting the dot as decimal separator, as well as replacing comma with dots, so both characters are used for decimals
var nfi = new NumberFormatInfo { NumberDecimalSeparator = "." };
height = double.Parse(heightString.Replace(',', '.'),nfi);
Different .Net cultures (countries) have different decimal separators.
If you expect input values to be in some specific format - either use some particular culture or InvariantCulture. Also consider using double.Parse as it geve more flexibility on parsing the values than generic Convert.ToDouble.
var d = double.Parse(heightString, CultureInfo.InvariantCulture);
If you expect user to enter value in local format - your code is fine, but either your expectation of "local format" is wrong, or "current culture" set incorrectly.

Input string was not in a correct format. calling TimeSpan.FromSeconds(Convert.ToDouble(time)) in IE on Changing Culture

Hi i m using given below method to convert in to string its working fine chrome but in IE its through exception Input string was not in a correct format. at this line
s = TimeSpan.FromSeconds(Convert.ToDouble(time));
these are values i m passing to it
600, 298.8, 65505, 69, 70, 20.5, 20.5, 20.5, 20.5, 1840.4, 682, 1040.3
in chrome its working but in IE it gives exception on second value when i change the culture to french language please help me out what is the problem
public static String ConvertTimeToString(this string time)
{
if (String.IsNullOrEmpty(time))
{
return time;
}
TimeSpan s;
if (time.IndexOf(':') >= 0)
{
s = TimeSpan.Parse(time);
}
else
{
s = TimeSpan.FromSeconds(Convert.ToDouble(time));
}
return s.ConvertTimeToString();
}
The failure is probably in the call Convert.ToDouble. Your code probably executes in a CultureInfo that has ',' as decimal separator, but your values use '.'. I would advice you to use Double.TryParse using a CultureInfo that has '.' as decimal separator instead:
Double value;
if (Double.TryParse(time, NumberStyles.Any, CultureInfo.GetCultureInfo("en-US"), out value))
{
s = TimeSpan.FromSeconds(value);
}
You need to specify an IFormatProvider when you use Convert.ToDouble(time):
Convert.ToDouble(time, CultureInfo.InvariantCulture)
Specifying CulturInfo.InvariantCulture specifies a culture that expect floating points written as 1.234 (note the period). The source of your problem may be that you time is in the format 1,234 (note the comma). Or maybe it is the reverse: You don't specify an IFormatProvider and the current culture of you ASP.NET process uses comma as a decimal separator, but the string provided uses period?
If the decimal point used isn't consistent you should either fix it at the source (not sure what the source is here) or as a last resort you can replace comma by period:
Convert.ToDouble(time.Replace(",", ".") , CultureInfo.InvariantCulture)
However, trying to parse a string and not knowing the what to expect is not the best thing to do.

Convert String into Double - Result is failing [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Reading a double value from a string
I have a problem with converting my String into a double, I always get strange results.
I want to convert the following string:
string Test = "17828.571428571";
I tried it like this (because it normally works):
Double _Test = Convert.ToDouble(Test);
Result is: 17828571428571 (without the dot, lol)
I need it as a double, to Math.Round() afterwards, so I have 17828 in my example.
My second idea was to split the string, but is that really the best method? :S
Thanks for helping me!
Finn
Use InvariantCulture
Double _Test = Convert.ToDouble(Test,CultureInfo.InvariantCulture);
EDIT: I believe your current culture is "German" de-DE, which uses , for floating point.
Tried the following code. You may also use NumberFormatInfo.InvariantInfo during conversion.
string Test = "17828.571428571";
System.Threading.Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
double d = Convert.ToDouble(Test);
double d2 = Convert.ToDouble(Test, CultureInfo.InvariantCulture);
double d3 = Convert.ToDouble(Test, NumberFormatInfo.InvariantInfo);
string Test2 = "17828,571428571"; //Notice the comma in the string
double d4 = Convert.ToDouble(Test2);
Console.WriteLine("Using comma as decimal point: "+ d4);
Output: (Notice the comma in the output)
Wihtout Invariant: 17828571428571
With InvariantCulture: 17828,571428571
With NumberFormatInfo.InvariantInfo: 17828,571428571
Using comma as decimal point: 17828,571428571
double _Test = double.Parse(Test,CultureInfo.InvariantCulture);
You need to set the format provider of the conversion operation to invariant.
Try Double.TryParse or Double.Parse if you are sure there is the correct format
EDIT: But take care of the format. as example if you are german you need to type 140,50 and not 140.50 because 140.50 would be 14050.
Or you pass as parameter that you dont care of culture (see other posts).

Categories