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

发布于 2024-11-18 11:27:19 字数 403 浏览 3 评论 0原文

在 VB.Net 中,有没有一种方法可以自动检测数字的字符串表示形式的区域性?我将解释一下这种情况:

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

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

我们开始从法国获取一些数据,其中一些价格是用句点和千位分隔符输入的,就像许多欧洲国家的做法一样。例如“999.000,00”。这就是我们的系统将其解释为九百九十九磅而不是预期的九十九万九千磅的地方。

不幸的是,数据源包含多种格式的价格,每种格式都没有任何文化指标。有谁知道任何内置的 .net 函数可以根据句点和逗号的位置自动检测字符串数字的区域性?

In VB.Net, is there a way of auto-detecting the culture of a string representation of a number? I'll explain the situation:

Our asp.net web site receives xml data feeds for boat data. Most of the time, the number format for the prices use either a simple non-formatted integer e.g. "999000". That's easy for us to process.

Occaisionally, there are commas for thousands separators and periods for the decimal point. Also, that's fine as our data import understands this. Example "999,000.00".

We're starting to get some data from France where some of the prices have been entered with the periods and thousands separators the other way around as that's the way it's done in many European countries. E.g. "999.000,00". This is where our system would interpret that as nine hundred and ninety nine pounds instead of the nine hundred and ninety nine thousand pounds that was intended.

Unfortunately, the data feed contains prices in a mixture of the formats without any culture indicator on each one. Does anyone know of any in-built .net functions that will auto-detect the culture of a string number based on where the period and comma are?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

脸赞 2024-11-25 11:27:19

我发现一个线程< /a> 在 vbforums 上建议如何通过区域性获取小数点分隔符。

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

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

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

I found a thread on vbforums suggesting how to get the decimal separator by culture.

I made a converter that converts between different files using oledb, excel object, mysql and more. Using "decimalSeparator" was the solution to get the number format working correctly when I converted to Excel and Access files.

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

cellValue = cellValue.Replace(".", decimalSeparator ).Replace(",", decimalSeparator )
赢得她心 2024-11-25 11:27:19

据我所知,没有内置方法可以根据数字字符串确定 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%安全,但它应该仍然比您当前的代码更好(并且至少在您提供的示例数据上按预期工作)。

There is no built-in way to determine the CultureInfo from a numeric string, as far as I know. And I seriously doubt it'll ever be, because there is no 100% safe way to do it.

Until you find a better solution (eg: some change on the sender-side), I guess the best you can do is to decrease the chances of error in two steps:

1) Input data cleanup and standardization:

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) Guess yourself the format:

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

You are not 100% safe this way, but it should be still better than your current code (and at least works as expected on the example data your provided).

☆獨立☆ 2024-11-25 11:27:19

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

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

Without knowing the specifics of how many differne ways the string can be formatted... This works for the three examples you gave

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
心在旅行 2024-11-25 11:27:19

'如果操作系统区域设置使用点作为小数点分隔符,则此变量为 True,在其他情况下为 false。

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

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

'This variable is True in case the O.S. Regional settings use a dot as decimal separator, false in the other cases.

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

Original post:
https://www.linkedin.com/groups/8141257/8141257-6347113651027079171

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文