1

While casting from string to double, the dot gets removed, eg. for 0.01 after casting to double it gives 1, or for 3.22 it gives 322.

Below is the Code I used.

In log file I get

Before Usage :- 0.01

After it Parse :- 1

while (reader.Read())
{
    XmlNodeType nType = reader.NodeType;
    if (nType == XmlNodeType.Element && reader.Name == "DepartmentUser")
    {
        UserData user = new UserData();
        while (reader.MoveToNextAttribute())
        {
            if (reader.Name == "UserName")
            {
                user.UserName = Convert.ToString(reader.Value);
            }
            else if (reader.Name == "UserID")
            {
                user.UserGUID = Convert.ToString(reader.Value);
            }
            else if (reader.Name == "UserUsage")
            {
                Logger.TraceLog(LogLevel.Debug, string.Format("Before Usage :- {0}", reader.Value));
                //user.DiskUsage = Convert.ToDouble(reader.Value);
                user.UserUsage = double.Parse(reader.Value);
                Logger.TraceLog(LogLevel.Debug, string.Format("After it Parse :- {0}", user.UserUsage));
            }
        }
    }
}

Is this due to Culture?

Maciej Los
  • 8,468
  • 1
  • 20
  • 35
Somnath
  • 249
  • 3
  • 12
  • I don't know why it would do that but you could simply divide it by 100 after converting to get the original number. But the question did get my curiosity. so ill take a look if it's the same for me. – maam27 Apr 24 '15 at 10:30
  • Definitely culture settings, you will most likely have the decimal separator set to a comma – Sayse Apr 24 '15 at 10:31
  • 1
    Note that parsing and casting are different things. You're not *casting* to double at all. – Jon Skeet Apr 24 '15 at 10:32
  • @somnath okey i tried it out and i see why its doing it. it has to do a little with the culture as it seems to use a diffrent decimal seperator use comma instead and it will work fine. – maam27 Apr 24 '15 at 10:32
  • Thanks @Sayse for advice i will do like that. – Somnath Apr 24 '15 at 10:40

4 Answers4

3

You could try, this would make the result culture-insensitive.

double.Parse(reader.Value, System.Globalization.CultureInfo.InvariantCulture);
Colin Bacon
  • 15,436
  • 7
  • 52
  • 72
3

I strongly suspect this is indeed a culture issue - your thread's current culture probably uses . as a grouping separator rather than a decimal separator. In fact, in some cultures your code would just fail with an exception. Here's an example demonstrating the problem:

using System;
using System.Globalization;
using System.Threading;

class Test
{
    static void Main()
    {
        var german = CultureInfo.GetCultureInfo("de-DE");
        var english = CultureInfo.GetCultureInfo("en-GB");
        var text = "1.5";

        Thread.CurrentThread.CurrentCulture = german;
        Console.WriteLine(double.Parse(text) == 1.5); // False

        Thread.CurrentThread.CurrentCulture = english;
        Console.WriteLine(double.Parse(text) == 1.5); // True
    }
}

Given that you're converting the content of XML, I'd use XmlConvert.ToDouble instead. That will "do the right thing" assuming that the XML follows the standard representation (which it appears to here).

In this case that will be equivalent to specifying the invariant culture when calling double.Parse (I believe) but I'd prefer the XmlConvert approach because:

  • It's more "clearly correct" for the context
  • It's a pattern you can apply to other types (e.g. DateTime)

Note that if you can possibly read the whole XML document in using LINQ to XML instead, you're likely to find that simpler - and then you can just cast the attribute to double instead. (XmlReader is a pain in the neck - I'd recommend only using it when you really have to due to document size... even then, you could load subtrees into LINQ to XML types.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thanks @Jon I have used like this user.UserUsage = XmlConvert.ToDouble(reader.Value); but it showing comma(,) instead of Dot(.) i.e 3.22 convert to 3,22 – Somnath Apr 24 '15 at 12:44
  • @Somnath: What do you mean by "it showing"? What's showing the value? The log? Don't forget that the value itself (when parsed) is just a number. If you want to log in a particular culture, you should change your `string.Format` call to do so. – Jon Skeet Apr 24 '15 at 12:48
  • the result in the log file is Before Usage :- 3.22 and After it Parse :- 3,22.The default culture is en.US – Somnath Apr 24 '15 at 12:58
  • @Somnath: I really don't think the default culture *is* en-US there. Log it: `Logger.TraceLog(LogLevel.Debug, string.Format("Culture: {0}", CultureInfo.CurrentCulture));`. What *possible* `double` value would you expect to be formatted as `3,22` in the US culture? – Jon Skeet Apr 24 '15 at 13:00
  • i log it as Logger.TraceLog(LogLevel.Debug, string.Format("Current Culture :- {0},After it Parse :- {1}", System.Globalization.CultureInfo.CurrentUICulture, user.DiskUsage)), in log file Current Culture :- en.US,After it Parse :- 3,22 i want to format it as 3.22 in US. – Somnath Apr 24 '15 at 13:12
  • @Somnath: That's `CurrentUICulture`, which isn't the same thing. Use `CurrentCulture`, as I suggested before. (`CurrentUICulture` is used for looking up resources; `CurrentCulture` is used for format patterns etc, as I understand it.) – Jon Skeet Apr 24 '15 at 13:12
  • now i get like this Current Culture :- nl-BE,After it Parse :- 3,63 – Somnath Apr 24 '15 at 13:41
  • @Somnath: So there you are. `nl-BE` (Belgium) is the culture being used to parse and format numbers. You asked how to fix the parsing - I've shown that. To fix the logging, pass in the culture you want to log in... – Jon Skeet Apr 24 '15 at 13:42
-1

Try using Convert.ToDouble instead

https://msdn.microsoft.com/en-us/library/zh1hkw6k(v=vs.110).aspx

garryp
  • 5,508
  • 1
  • 29
  • 41
  • 1
    "Using the ToDouble(String) method is equivalent to passing value to the Double.Parse(String) method. value is interpreted by using the formatting conventions of the current thread culture." – Jon Skeet Apr 24 '15 at 10:36
  • As I understood they were different. Have a look at this post for int.parse vs ToInt32 http://stackoverflow.com/questions/199470/whats-the-main-difference-between-int-parse-and-convert-toint32. I haven't spent a lot of time stying this though. – garryp Apr 24 '15 at 10:52
  • 1
    There are differences if you have a value of type `object` instead of `string`, and if the value is `null`. Those differences aren't relevant here. – Jon Skeet Apr 24 '15 at 10:55
-2

To parse your string to a double you need to use conver.ToDouble().

Regards!

  • Why would the OP "need" to use that rather than `double.Parse`? And why do you think it would behave any differently, given the remarks of the documentation you linked to? – Jon Skeet Apr 24 '15 at 10:36