检测 VB.Net 中数字的文化,即小数点/千位分隔符的句点或逗号

Posted

技术标签:

【中文标题】检测 VB.Net 中数字的文化,即小数点/千位分隔符的句点或逗号【英文标题】:Detect culture of number in VB.Net i.e. period or comma for decimal point / thousands separator 【发布时间】:2011-09-26 21:13:26 【问题描述】:

在 VB.Net 中,有没有一种方法可以自动检测数字字符串表示的文化?我来解释一下情况:

我们的 asp.net 网站接收船数据的 xml 数据馈送。大多数时候,价格的数字格式使用简单的非格式化整数,例如“999000”。这对我们来说很容易处理。

有时,千位分隔符使用逗号,小数点使用句点。此外,这很好,因为我们的数据导入理解这一点。示例“999,000.00”。

我们开始从法国获取一些数据,其中一些价格已经输入了句点和千位分隔符,因为许多欧洲国家都是这样做的。例如。 “999.000,00”。在这里,我们的系统会将其解释为 999 磅,而不是预期的 999000 磅。

很遗憾,数据馈送包含多种格式的价格,每种格式都没有任何文化指标。有谁知道任何内置的 .net 函数可以根据句点和逗号的位置自动检测字符串数字的文化?

【问题讨论】:

想想你在问什么,你会意识到答案是“不,当然不是”。相反,也许您应该将您的提要定义为仅接受整数。事实上,价格的货币单位是什么?欧元?也许其中一些数字是法郎? 我同意最好的方法是更清楚地定义提要格式。我们正在开发一个新版本——但在完成之前,我们一直在努力充分利用这一版本。货币单位在 Feed 的单独字段中定义。 那么也许货币可以告知您对价格格式的看法? 对此有任何公认的答案吗?如果你能接受其中一个和/或评论它会很好,所以我们都可以跟随你的脚步。 TIMINeutron,是的,我很抱歉直到现在才回到这里。谢谢大家的回复。我认为最终 John Saunders 给出了答案——我们只需要继续修复提要格式并做好记录,以便清楚应该使用哪种格式。 【参考方案1】:

我在 vbforums 上找到了a thread,建议如何按文化获取小数点分隔符。

我制作了一个转换器,可以使用 oledb、excel 对象、mysql 等在不同文件之间进行转换。当我转换为 Excel 和 Access 文件时,使用“decimalSeparator”是让数字格式正常工作的解决方案。

Dim decimalSeparator As String = Globalization.CultureInfo.CurrentCulture.NumberFormat.NumberDecimalSeparator

cellValue = cellValue.Replace(".", decimalSeparator ).Replace(",", decimalSeparator )

【讨论】:

这确实是解决这个问题的方法。简单、准确且不基于用户输入。【参考方案2】:

据我所知,没有内置方法可以从数字字符串中确定 CultureInfo。而且我严重怀疑它永远不会发生,因为没有 100% 安全的方法来做到这一点。

在您找到更好的解决方案之前(例如:在发送方进行一些更改),我想您能做的最好的事情就是分两步减少出错的机会:

1)输入数据的清理和标准化

Dim input as String = " 99 9.000,00 "
' This way you can remove unwanted characters (anything that is not a digit, and the following symbols: ".", "-", ",")
Dim fixedInput as String = Regex.Replace(input, "[^\d-,\.]", "")
' fixedInput now is "999.000,00"

2) 自己猜格式

Dim indexOfDot as Integer = fixedInput.IndexOf(".")
Dim indexOfComma as Integer = fixedInput.IndexOf(",")
Dim cultureTestOrder as List(Of CultureInfo) = new List(Of CultureInfo)
Dim parsingResult as Double?
Try
    If indexOfDot > 0 And indexOfComma > 0 Then
        ' There are both the dot and the comma..let's check their order
        If indexOfDot > indexOfComma Then
            ' The dot comes after the comma. It should be en-US like Culture
            parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"))
        Else
            ' The dot comes after the comma. It should be it-IT like Culture
            parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("it-IT"))
        End If
    Else If indexOfDot = fixedInput.Length-3 Then
        ' There is only the dot! And it is followed by exactly two digits..it should be en-US like Culture
        parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("en-US"))
    Else If indexOfComma = fixedInput.Length-3 Then
        ' There is only the comma! And it is followed by exactly two digits..it should be en-US like Culture
        parsingResult = Double.Parse(fixedInput, NumberStyles.Number, CultureInfo.GetCultureInfo("it-IT"))
    End If
Catch
End Try
If Not parsingResult.HasValue Then
    Try
        ' There is no dot or comma, or the parsing failed for some reason. Let's try a less specific parsing.
        parsingResult = Double.Parse(fixedInput, NumberStyles.Any, NumberFormatInfo.InvariantInfo)
    Catch
    End Try 
End If
If Not parsingResult.HasValue Then
    ' Conversion not possible, throw exception or do something else
Else
    ' Use parsingResult.Value
End If

这种方式不是 100% 安全的,但它应该仍然比您当前的代码更好(并且至少在您提供的示例数据上按预期工作)。

【讨论】:

谢谢 Fulvio - 我会试试这个和 debasnett 的方法。【参考方案3】:

不知道字符串可以格式化多少种不同方式的细节...这适用于您提供的三个示例

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    Dim v As String = "999.123,45"
    Debug.WriteLine(foo(v))

    v = "999,123.45"
    Debug.WriteLine(foo(v))

    v = "999123"
    Debug.WriteLine(foo(v))
End Sub

Private Function foo(value As String) As Double
    Dim style As NumberStyles = NumberStyles.AllowThousands Or NumberStyles.AllowDecimalPoint
    Dim culture As CultureInfo = CultureInfo.InvariantCulture
    Dim rv As Double
    If Double.TryParse(value, style, culture, rv) Then
        Debug.WriteLine(",.Converted '0' to 1.", value, rv)
    Else
        Dim styleES As NumberStyles = NumberStyles.AllowThousands Or NumberStyles.AllowDecimalPoint
        Dim cultureES As CultureInfo = CultureInfo.CreateSpecificCulture("es-ES")

        If Double.TryParse(value, styleES, cultureES, rv) Then
            Debug.WriteLine(".,Converted '0' to 1.", value, rv)
        Else
            Throw New ArgumentException
        End If
    End If
    Return rv
End Function

【讨论】:

谢谢 - 我会试试看。【参考方案4】:

'这个变量在 OS 的情况下为 True。区域设置使用点作为小数分隔符,其他情况下为 false。

Dim bAmerican as boolean=Cdec("0,2") > 1

原帖: https://www.linkedin.com/groups/8141257/8141257-6347113651027079171

【讨论】:

以上是关于检测 VB.Net 中数字的文化,即小数点/千位分隔符的句点或逗号的主要内容,如果未能解决你的问题,请参考以下文章

VB.NET 根据所选文化格式化数字

货币上的符号是啥?

vb.net怎么设置数字保留小数点位数

在 Swift 中将小数点后的逗号和零值添加到千位后的数字字符串中

千位分组来格式化数字函数

在python中使用本地化的千位分隔符和小数精度格式化数字