【问题标题】:decimal.TryParse() drops leading "1"decimal.TryParse() 丢弃前导“1”
【发布时间】:2010-03-30 09:30:50
【问题描述】:

短而甜的版本:

在大约一百台测试机器中的一台机器上,十进制。TryParse() 将“1.01”转换为 0.01


好吧,这听起来很疯狂,但请耐心等待......

我们有一个客户端应用程序通过 JSON 与 web 服务通信,该服务返回一个十进制值作为字符串,因此我们将其作为字符串存储在我们的模型对象中:

[DataMember(Name = "value")]
public string Value { get; set; }

当我们在屏幕上显示该值时,它被格式化为特定的小数位数。所以我们使用的过程是字符串->十进制然后十进制->字符串。

该应用程序目前正在进行最终测试,并在 100 多台机器上运行,一切正常。但是,在 one 机器上,如果十进制值有一个前导“1”,那么它将被一个零替换。我在代码中添加了简单的日志记录,所以它看起来像这样:

Log("Original string value: {0}", value);
decimal val;
if (decimal.TryParse(value, out val))
{
    Log("Parsed decimal value: {0}", val);
    string output = val.ToString(format, CultureInfo.InvariantCulture.NumberFormat);
    Log("Formatted string value: {0}", output);
    return output;
}

在我的机器上 - 任何其他客户端机器上 - 日志文件输出是:

  • 原始字符串值:1.010000
  • 解析十进制值:1.010000
  • 格式化字符串值:1.01

在有缺陷的机器上,输出是:

  • 原始字符串值:1.010000
  • 解析十进制值:0.010000
  • 格式化字符串值:0.01

因此,decimal.TryParse 方法似乎有问题。

我们尝试过的事情:

  • 卸载并重新安装客户端应用程序
  • 卸载并重新安装 .net 3.5 sp1
  • 将有缺陷机器的数字区域设置(使用英语(英国))与工作机器的区域设置进行比较 - 没有差异。

有没有人见过这样的事情或有什么建议?我的想法很快就用完了...


当我输入此内容时,出现了更多信息:将字符串值“10000”传递给 Convert.ToInt32() 返回 0,因此这似乎也去掉了前导 1。


基于 cmets 的进一步测试:

  • 1.01 -> 0.01
  • 111.01 -> 11.01
  • 123.01 -> 23.01
  • 231.01 -> 231.01
  • 01.01 -> 1.01

所以看起来它只影响 1 并且只有当它们是字符串的第一个字符时。很奇怪,但至少它是一致的。

【问题讨论】:

  • 很奇怪。其他数字如“123”或“321”会怎样?
  • 机器内存不足?您是否尝试过运行 memtest86 之类的东西?
  • 这是一个非常糟糕的主意,但如果你预先用零填充......?
  • 尝试输入 2.010000 或 9.010000 的结果是什么?
  • 把机器拿出去停车场,然后用你的车把它放回去。几次,以确保。问题解决了。

标签: .net


【解决方案1】:

我能够重现您的结果。 考虑:

public NumberFormatInfo OneIsPositiveSignFormat()
{
    NumberFormatInfo custom = new NumberFormatInfo();
    custom.PositiveSign = "1";
    return custom;
}

然后:

if (decimal.TryParse(value, NumberStyles.Number, OneIsPositiveSignFormat(), out val))

问题是:区域设置没有显示当前的正号,主要是:你在解析数字时没有设置文化。

该值可能来自不同的位置:它可能来自注册表作为系统默认值,或者默认值可能已由代码设置:

CultureInfo customCulture = (CultureInfo)CultureInfo.InvariantCulture.Clone();
customCulture.NumberFormat = OneIsPositiveSignFormat();
Thread.CurrentThread.CurrentCulture = customCulture;

【讨论】:

  • 有趣的答案,但它引出了一个问题,如果区域设置不允许您设置正号,并且OP的区域设置与其他机器相同,正号怎么可能有被改变了?我没有不同意你的观点,它完全符合这些例子,我只是好奇。
  • 我们有一个赢家!只需在他的机器上运行以下代码: Console.WriteLine(System.Globalization.CultureInfo.CurrentCulture.NumberFormat.PositiveSign);它输出“1”。现在,只需要弄清楚如何将它改回来......
  • 我敢打赌是第三方程序做到了这一点。真是个怪物。
  • 乐于助人。我找不到此的注册表设置(应该在 HKEY_CURRENT_USER\Control Panel\International 上),但也许可以添加。
【解决方案2】:

查看如何为这台计算机设置区域设置,它可能是“。”设置为千位分隔符而不是小数分隔符。尝试使用 Decimal.TryParse (String, NumberStyles, IFormatProvider, out Decimal val) 并传递使用小数分隔符“。”创建的 NumberFormatInfo。

【讨论】:

  • OP 已经说过区域设置没有差异 - 另外,如果在 . 是千位分隔符时输入 1.000,它将给出 1000,而不是 0。
猜你喜欢
  • 2019-06-15
  • 2013-02-06
  • 1970-01-01
  • 1970-01-01
  • 2010-10-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多