代码之家  ›  专栏  ›  技术社区  ›  rick schott

StringBuilder.Append和Float

  •  4
  • rick schott  · 技术社区  · 15 年前

    StringBuilder.Append 使用 float 正在截断值。它转换为什么?如何阻止它截断?

    AttributeOrder IS型 浮动 我在做绳子的时候会失去精确性。

    if ( AttributeOrder != 0 ) 
    { 
        if ( Result.Length > 0 ) 
        { 
            Result.Append( " AND " ); 
        } 
        Result.Append( COLUMN_ATTRIBUTE_ORDER ); 
        Result.Append( "=" ); 
        Result.Append( AttributeOrder ); 
    } 
    

    编辑:这是旧代码,我无法更改基础数据类型。SQL Server中的列是实数,数据类型为 浮动 . 我需要呈现 浮动 因为它是填充的,作为一个字符串用于其他目的,而不是松散的精度。

    5 回复  |  直到 11 年前
        1
  •  4
  •   SLaks    15 年前

    您可以转换 float 使用 format string ,像这样:

    Result.Append(AttributeOrder.ToString("G9"))
    

    或者,或者,

    Result.AppendFormat("{0}={1:G9}", COLUMN_ATTRIBUTE_ORDER, AttributeOrder)
    

    但是,您将无法从 浮动 ,数字8和9将不准确。


    这个 float datatype 只能保持七位数的精度。一旦你把价值 浮动 变量,你已经失去了不可恢复的精度。为了存储来自SQL Server的所有24位精度,需要使用 decimal datatype .

    一旦将变量更改为 十进制的 , Append 会给你尽可能多的数字。

        2
  •  2
  •   Andrew Hare    15 年前

    如果您需要提供 表现 如果是浮点数,则应使用 System.Decimal - System.Single 无法准确表示要显示的精度。

    这个简单的例子显示了不同之处:

    using System;   
    
    class Test
    {
        static void Main()
        {
            Single s = 1.23456789f;
            Decimal d = 1.23456789m;
    
            Console.WriteLine(s);
            Console.WriteLine(d);
        }
    }
    
        3
  •  2
  •   Jeffrey L Whitledge    15 年前

    让我们来玩玩花车,看看为什么不管用。

    假设24位数字1.23456789012345678901234从SQL中读取 real 进入.NET float .

    浮点值的二进制形式如下: 0 01111111 00111100000011001010010

    第一 0 是符号位,表示数字为正数。 01111111 是有偏差的指数,表示有效位乘以2^0(或1)。 00111100000011001010010 是数字的位数,减去第一位。

    所以float变量现在用二进制编码数字1.001111000000110010。

    让我们看看当我们把这个浮点转换成十进制时会发生什么。

    1 * 1 =                         1
    .
    0 * 0.5 =                       0
    0 * 0.25 =                      0
    1 * 0.125 =                     0.125
    1 * 0.0625 =                    0.0625
    1 * 0.03125 =                   0.03125
    1 * 0.015625 =                  0.015625
    0 * 0.0078125 =                 0
    0 * 0.00390625 =                0
    0 * 0.001953125 =               0
    0 * 0.0009765625 =              0
    0 * 0.00048828125 =             0
    0 * 0.000244140625 =            0
    1 * 0.0001220703125 =           0.0001220703125
    1 * 0.00006103515625 =          0.00006103515625
    0 * 0.000030517578125 =         0
    0 * 0.0000152587890625 =        0
    1 * 0.00000762939453125 =       0.00000762939453125
    0 * 0.000003814697265625 =      0
    1 * 0.0000019073486328125 =     0.0000019073486328125
    0 * 0.00000095367431640625 =    0
    0 * 0.000000476837158203125 =   0
    1 * 0.0000002384185791015625 =  0.0000002384185791015625
    0 * 0.00000011920928955078125 = 0
                                    ------------------------
                                    1.2345678806304931640625
    

    所以如果我们展示 全部的 在浮点数的位数中,我们得到1.234567806304931640625。 这不是我们要显示的号码吗?为什么要四舍五入这个数字?为什么这个值与我们开始使用的数字不同?

    要了解原因,让我们逐步了解几个相邻的浮点值:

    binary floating point representation   decimal representation
    ------------------------------------   ----------------------
    0 01111111 00111100000011001010000   = 1.2345676422119140625
    0 01111111 00111100000011001010001   = 1.23456776142120361328125
    0 01111111 00111100000011001010010   = 1.2345678806304931640625
    0 01111111 00111100000011001010011   = 1.23456799983978271484375
    0 01111111 00111100000011001010100   = 1.234568119049072265625
    

    如您所见,使用完全相同的浮点数表示此范围内的所有值:[1.234567821022584838671875,1.2345679435137939453125)

    因此,在转换为浮点数的过程中,第8位之后的任何十进制数字都会丢失,并且可能显示的任何数字都是完全无意义的,与正在表示的实际值无关。

    第八位以外的所有十进制数字都是舍入为24位二进制并转换为十进制的伪影,它们没有实际意义。

        4
  •  0
  •   Blindy    15 年前

    你可以一直使用 ToString() 方法,如下所示:

    if ( AttributeOrder != 0 ) 
    { 
        if ( Result.Length > 0 ) 
        { 
            Result.Append( " AND " ); 
        } 
        Result.Append( COLUMN_ATTRIBUTE_ORDER ); 
        Result.Append( "=" ); 
        Result.Append( AttributeOrder.ToString("0.000000") ); 
    } 
    

    例如,上面的格式说明符显示6个小数位。更换 0 具有 # 如果不想显示尾随零。

        5
  •  0
  •   mbmcavoy    15 年前

    你可以用 string.Format() . 减少代码行数,并以任意精度显示数字。

    Result.Append(string.Format("{0}={1:0.000000}", COLUMN_ATTRIBUTE_ORDER, AttributeOrder));