在 ASP.NET 中将具有小数语言中性的价格值转换为整数

Posted

技术标签:

【中文标题】在 ASP.NET 中将具有小数语言中性的价格值转换为整数【英文标题】:Convert price values with decimals language neutral to an integer in ASP.NET 【发布时间】:2014-09-10 22:05:14 【问题描述】:

我想转换十进制数(准确的价格值),这可能: a) 包含 1 或 2 位小数 b) 使用., 作为小数分隔符

以美分为单位的整数值。

所以:

3,5 变为 350 3,50 变为 350 3.5变成350 3.50 变成 350 1,000.34 变为 100034 1.000,34 变为 100034

如果不构建执行所有这些检查的函数,ASP.NET 中是否可以更快地完成这些检查?

**更新** 感谢尼古拉斯:

我现在在 VB.NET 中有这个

Private Shared Function ConvertToPriceInCents(s As String) As Integer
        If s Is Nothing Then
            Throw New ArgumentNullException("s")
        End If
        If s = "" Then
            Throw New ArgumentOutOfRangeException("s", "s must not be empty.")
        End If

        Dim priceInCents As Integer = 0
        Dim scale As Integer = 1
        Dim i As Integer = s.Length

        ' collect the fractional part; identify the decimal separator
        While System.Threading.Interlocked.Decrement(i) >= 0
            Dim n As Integer = Asc(s(i)) - Asc("0"c)

            If n < 0 OrElse n > 9 Then
                Exit While
            End If
            ' bail out, we found the decimal separator
            priceInCents += n * scale

            scale *= 10
        End While

        Dim decimalSeparator As Char = s(i)
        Dim groupSeparator As Char = If(decimalSeparator = "."c, ","c, "."c)

        If scale <> 10 AndAlso scale <> 100 Then
            Throw New FormatException("value must have 1 or 2 digits to the right of the decimal separator")
        End If
        If decimalSeparator <> ","c AndAlso decimalSeparator <> "."c Then
            Throw New FormatException("Invalid decimal separator")
        End If

        ' if we only found one digit to the right of the decimal separator,
        ' we need to normalize and scale up by a factor of 10 (so something like 3.5 represents 350 cents)
        If scale = 10 Then
            scale *= 10
            priceInCents *= 10
        End If

        ' get the integer portion of value
        ' we're being a little lax here and ignoring group separators regardless of position.
        ' It's a hard thing to do, especially when you consider that
        ' - group sizes vary across cultures, and
        ' - aren't necessarily uniform in size.
        While System.Threading.Interlocked.Decrement(i) >= 0
            Dim c As Char = s(i)
            If c = groupSeparator Then
                Continue While
            End If

            Dim n As Integer = Asc(s(i)) - Asc("0"c)
            If n < 0 OrElse n > 9 Then
                Throw New FormatException("invalid group separator")
            End If

            priceInCents += n * scale

            scale *= 10
        End While

        ' If we haven't thrown an exception yet,
        ' we have the value in cents: return it.
        Return priceInCents
    End Function

【问题讨论】:

【参考方案1】:

您编写的方法如下所示:

static int ConvertToPriceInCents( string s )

  if ( s == null ) throw new ArgumentNullException("s") ;
  if ( s == ""   ) throw new ArgumentOutOfRangeException("s","s must not be empty." ) ;

  int priceInCents = 0 ;
  int scale        = 1 ;
  int i            = s.Length ;

  // collect the fractional part; identify the decimal separator
  while ( --i >= 0 )
  
    int n = s[i] - '0' ;

    if ( n < 0 || n > 9 ) break ; // bail out, we found the decimal separator

    priceInCents += n*scale ;
    scale *= 10 ;

  

  char decimalSeparator = s[i] ;
  char groupSeparator   = decimalSeparator == '.' ? ',' : '.' ;

  if ( scale            != 10  && scale            != 100 ) throw new FormatException("value must have 1 or 2 digits to the right of the decimal separator") ;
  if ( decimalSeparator != ',' && decimalSeparator != '.' ) throw new FormatException("Invalid decimal separator") ;

  // if we only found one digit to the right of the decimal separator,
  // we need to normalize and scale up by a factor of 10 (so something like 3.5 represents 350 cents)
  if ( scale == 10 )
  
    scale        *= 10 ;
    priceInCents *= 10 ;
  

  // get the integer portion of value
  // we're being a little lax here and ignoring group separators regardless of position.
  // It's a hard thing to do, especially when you consider that
  // - group sizes vary across cultures, and
  // - aren't necessarily uniform in size.
  while ( --i >= 0 )
  
    char c = s[i] ;
    if ( c == groupSeparator ) continue ;

    int n = s[i] - '0' ;
    if ( n < 0 || n > 9 ) throw new FormatException("invalid group separator") ;

    priceInCents += n*scale ;
    scale        *= 10      ;

  

  // If we haven't thrown an exception yet,
  // we have the value in cents: return it.
  return priceInCents ;

【讨论】:

我添加了您的代码的 VB.NET 翻译,但它仍然包含一些错误...您知道如何修复它们吗?

以上是关于在 ASP.NET 中将具有小数语言中性的价格值转换为整数的主要内容,如果未能解决你的问题,请参考以下文章

以下哪个代码在 ASP.NET 2.0 中性能更好

如何在 .NET 中将双精度值转换为具有固定小数位数的小数类型值

[C++]jsoncpp中将整个Json::Value转成std::string或者把里面值转成string类型

[C++]json cpp中将整个Json::Value转成std::string或者把里面值转成string类型

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

如何在 asp .NET 中将记录添加到数据库中