使用任何小数分隔符将字符串解析为十进制
我想解析从Text输入到十进制的字符串。 该值表示货币值。
目前我有这个解决方案:
private Decimal CastToDecimal(string value) { Decimal result; var valid = Decimal.TryParse(value, NumberStyles.Currency, null, out result); return valid ? result : -1; }
到目前为止,这种方法效果很好,除了可能的文化差异。 我是德国人,我希望大多数用户进入德国风格的标点。 但有可能有人使用“。” 而不是“,”,转换将失败。
“123,45€”=> 123.45
“123.456,78€”=> 123456.78
“123.45€”=> 12345 < – 我希望结果在这里是123.45
有没有办法自动检测使用的文化的十进制值? 如果您使用德语或英语标点符号无关紧要,您仍会得到相同的结果吗?
更新:
感谢您的帮助,我创建了一种方法,可以满足我的需求(我认为)。
private static Decimal CastToDecimal(string value) { Decimal resultDe; Decimal resultEn; var style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands; var cultureDe = CultureInfo.CreateSpecificCulture("de-DE"); var cultureEn = CultureInfo.CreateSpecificCulture("en-GB"); var deValid = Decimal.TryParse(value, style, cultureDe, out resultDe); var enValid = Decimal.TryParse(value, style, cultureEn, out resultEn); var minVal = Math.Min(resultDe, resultEn); var maxVal = Math.Max(resultDe, resultEn); if (!deValid) return resultEn; if (!enValid) return resultDe; return BitConverter.GetBytes(decimal.GetBits(minVal)[3])[2] > 2 ? maxVal : minVal; }
这段代码……
Console.WriteLine(CastToDecimal("123,45")); Console.WriteLine(CastToDecimal("123.45")); Console.WriteLine(CastToDecimal("123,450")); Console.WriteLine(CastToDecimal("123.450")); Console.WriteLine(CastToDecimal("123.123,45")); Console.WriteLine(CastToDecimal("123,123.45"));
返回:
123,45 123,45 123450 123450 123123,45 123123,45
https://msdn.microsoft.com/en-us/library/3s27fasw%28v=vs.110%29.aspx中包含设置NumberStyle的解决方案可能会有所帮助。
... value = "1.345,978"; style = NumberStyles.AllowDecimalPoint | NumberStyles.AllowThousands; culture = CultureInfo.CreateSpecificCulture("es-ES"); if (Double.TryParse(value, style, culture, out number)) Console.WriteLine("Converted '{0}' to {1}.", value, number); else Console.WriteLine("Unable to convert '{0}'.", value); // Displays: // Converted '1.345,978' to 1345.978. value = "1 345,978"; if (Double.TryParse(value, style, culture, out number)) Console.WriteLine("Converted '{0}' to {1}.", value, number); else Console.WriteLine("Unable to convert '{0}'.", value); ...
我前段时间遇到过同样的问题。 我的解决方案是用Java编写自己的解析器。 该算法首先清理字符串。 简要说明如下:
- 从左到右扫描字符串
- 如果char =’。’ 然后dotFound = true; lastSeparatorPosition = index; 点++
- 如果char =’,’那么commaFound = true; lastSeparatorPosition = index; 逗号++
- 如果dots == 0 && commas == 0则其整数=>完成
- 如果点> 0 &&逗号> 0,那么lastSeparatorPosition中的那个是小数分隔符。 从字符串=>完成中删除其他人
- / *只有一个分隔符类型* / if(点+逗号)> 1然后删除它们//因为必须是千位分隔符=>完成
- / *分隔符出现一次* /如果numberOfDigits右边的分隔符== 3那么你必须决定:-)整数或小数,3位数的分数
7是唯一一个像chiastic-security已经说过的问题。 在这里,您只能考虑概念环境。 所有其他情况都是安全的。
玩得开心
这是不可能的,因为有两种不同文化中有意义的字符串,但意味着不同的东西。 例如:
123.456 123,456
第一个在英国有123个,但在德国有123456个; 第二个是英国的123456,但在法国略高于123。
唯一的解决方案是在输入上添加validation,如果它是一个网页,则为用户提供示例,然后根据用户的文化找到获取输入的方法。 我建议你不要尝试做你正在尝试的事情,因为有些文化与货币相互矛盾;
美国/澳大利亚/许多其他人使用以下格式
45,999.95
在哪里,是千分隔符和。 是小数点分隔符
而在一些欧洲国家
45.999,95
意思是与上面相同但千位分隔符。 并用作小数分隔符。
现在问题是无法保证用户同时使用两个分隔符,您的系统可能会假设千位分隔符为十进制,依此类推。
如果您真的不想打扰用户,请为主要货币和次要货币创建单独的输入字段。
所以最好不去那里。 我相信这可能会有所帮助。 快乐编码:)
更新 :
同样的情况是日期格式,例如以美国格式月份首先出现,然后是一天,而在澳大利亚日出现第一个月然后现在是2015年1月2日输入将意味着不同的系统无法说明用户的意图。
上述就是C#学习教程:使用任何小数分隔符将字符串解析为十进制分享的全部内容,如果对大家有所用处且需要了解更多关于C#学习教程,希望大家多多关注—计算机技术网(www.ctvol.com)!
本文来自网络收集,不代表计算机技术网立场,如涉及侵权请联系管理员删除。
ctvol管理联系方式QQ:251552304
本文章地址:https://www.ctvol.com/cdevelopment/1039378.html