C# StringBuilder.Append与float

C# StringBuilder.Append与float,c#,asp.net,C#,Asp.net,StringBuilder.Append使用float将截断该值。它转换为什么?如何阻止它截断 AttributeOrder是类型float,我在构建字符串时会丢失精度 if ( AttributeOrder != 0 ) { if ( Result.Length > 0 ) { Result.Append( " AND " ); } Result.Append( COLUMN_ATTRIBUTE_ORDER ); Re

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

AttributeOrder
是类型
float
,我在构建字符串时会丢失精度

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

编辑:这是遗留代码,我无法更改基础数据类型。SQL Server中的列是实数,数据类型为
float
。我需要在填充时将
浮点数
表示为字符串,以用于其他目的,而不是像现在这样精度不高。

您可以使用a将
浮点数
转换为字符串,如下所示:

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

Result.AppendFormat("{0}={1:G9}", COLUMN_ATTRIBUTE_ORDER, AttributeOrder)
但是,您将无法从
浮点
中获得超过9位的精度,并且数字8和9将不准确


这个数字只能容纳七位数的精度。一旦将该值放入
float
变量中,就无法恢复精度。为了存储来自SQL Server的所有24位精度,您需要使用


一旦您将变量更改为
十进制
Append
将为您提供输入的位数。

您始终可以在浮点上使用
ToString()
方法,如下所示:

Result.Append(AttributeOrder.ToString("G9"))
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
替换为

如果需要提供浮点数的表示形式,则应使用
系统。十进制
-
系统。单个
无法准确表示要显示的精度

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

using System;   

class Test
{
    static void Main()
    {
        Single s = 1.23456789f;
        Decimal d = 1.23456789m;

        Console.WriteLine(s);
        Console.WriteLine(d);
    }
}

您可以使用
string.Format()
杀死多只鸟。减少代码行数,并以任意精度显示数字

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

让我们玩一些花车的乐趣,看看为什么这不起作用

假设24位数字1.2345678901234567801234从SQL
real
读入.Net
float

浮点值在二进制中如下所示:
0 01111111 00111100000011001010010

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

因此,float变量现在将数字1.00111100000011001010010编码为二进制

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

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.2345678806304931640625。 这不是我们要显示的数字吗?为什么要舍入这个数字?为什么这个值与我们开始时的数值不同

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

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.234567821025848388671875,1.234567940235137939453125)

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


所有超过8位的十进制数字都是舍入到24位二进制并转换为十进制的产物,它们没有实际意义。

这是SQL Server real底层数据类型的遗留代码。格式化程序是否有最大精度?如果使用
十进制
类型,则无需担心spe指定精度-表示精度(即数字显示为字符串)正是您设置的值。@Andrew Hare-小数点将显示存储值的精确值,但这不一定就是您设置的值!@rick schott-我认为格式设置程序的精度不值得关注,而是变量的精度。如果您想要更高的精度,那么您应该切换到
double
@Jeffrey L Whitledge我的问题不在于变量,而在于何时需要将其表示为字符串。即使您指定这样的格式,您的解决方案也会受到
float无法以高精度表示浮点数的影响。是的。出于某种原因,我假设他知道真实的数据类型与float(24)相同——一种小数点右边有24位数字的浮点数据类型。那么,我可以安全地使用“G24”吗作为我的格式,永远不会失去精度?不。一旦你将值放入
浮点
,你就会失去精度。你需要将数据放入
十进制
,而不是
浮点
。明白,这不是我的问题,只需要按原样显示浮点,但它作为字符串出现,不再失去精度。如果你不能改变对于数据类型,您无法解决此问题。我不能采用float.NET数据类型并将其表示为字符串?您不能采用
float
并将其转换为24位字符串。如果您愿意接受9位数字,您可以;请参阅我答案的第一部分。您应该调用
AppendFormat
。调用
Append(string.Format(…)
违背了
StringBuilder
的目的。您仍然无法显示比
浮点值所能包含的精度更高的精度。