C#学习教程:查找具有相同内部表示的float/double的最小值/最大值涉及到转字符串时浮点数舍入的讨论,让我鼓捣一下:如何让给定浮点数的二进制表示的最大值和最小值相等。免责声明:对于本次讨论,我喜欢坚持使用IEEE-754描述的32位和64位浮点数。我对扩展浮点(80位)或四(128位IEEE-754-2008)或任何其他标准(IEEE-854)不感兴趣。背景:计算机在二进制表示法中表现不佳。在C#中,float在内部表示为3DCCCCCD(C#使用舍入到最接近的值),并表示为3FB999999999999A。相同的位模式用于十进制0.100000005(浮点数)和0.1000000000000000124(双精度0.1000000000000000124),但不用于0.1000000000000000144(双精度0.1000000000000000144)。为方便起见,以下C#代码给出了这些内部表示:stringGetHex(floatf){returnBitConverter.ToUInt32(BitConverter.GetBytes(f),0).ToString("X");}stringGetHex(doubled){returnBitConverter.ToUInt64(BitConverter.GetBytes(d),0).ToString("X");}//浮动Console.WriteLine(GetHex(0.1F));//双控制台.WriteLine(GetHex(0.1));在0.1的情况下,没有用相同位模式表示的低位十进制数,任何0.99...99都会产生不同的位表示(即,浮点数0.9999999373F7FFFFF在内部产生3F7FFFFF)。我的问题很简单:如何找到内部存储在相同二进制表示中的给定浮点数(或双精度数)的最低和最高十进制值。为什么:(我知道你会问)在转换为字符串时从.NET舍入时发现错误,找到内部精确值并更好地理解从字符串转换时我自己的舍入错误。我的猜测是这样的:取尾数,去掉其余的,得到它的精确值,得到更高的一个(尾数位),然后计算平均值:低于它的任何东西都会产生相同的位模式。我的主要问题是:如何将小数部分作为整数获取(位操作不是我最强的资产)。JonSkeet的DoubleConverter类可能会有所帮助。解决问题的一种方法是在浮动中找到ULP大小,或者在LastPlace中找到单位。稍微简化一下,这是给定浮点数与下一个更高数字之间的距离。同样,为了简化一点,给定一个可表示的浮点值x,任何值介于(x–1/2ulp)和(x+1/2ulp)之间的十进制字符串在转换为浮点数时将被舍入输入x-点值。诀窍在于(x+/-1/2ulp)不是可表示的浮点数,因此实际计算其值需要使用更宽的浮点类型(如果有的话)或任意宽的大小数字或类似计算。你如何找到ulp的大小?一个相对简单的方法大致就是你所建议的,用C-ish伪代码写在这里,因为我不知道C#:floatabsX=absoluteValue(x);uint32_tbitPattern=getRepresentationOfFloat(absx);位模式++;浮动nextFloatNumber=getFloatFromRepresentation(bitPattern);浮动ulpOfX=(nextFloatNumber-absX);这是可行的,因为将ulp添加到x的位模式与将ulp添加到x的值完全对应。减法不会出现浮点舍入,因为涉及的值非常接近(特别是有一个IEEE-754浮点算术定理,两个数x和y满足y/2x-y)。这里唯一需要注意的是:如果x恰好是最大的有限浮点数,这将不起作用(它将返回inf,这显然是错误的)。如果您的平台不能正确支持渐进下溢(例如在齐纳模式下运行的嵌入式设备),这将不适用于非常小的x值。听起来您不太可能处于这两种情况,因此这应该适合您的目的。既然知道了x的ulp是多少,就可以求取值四舍五入到x的区间了。您可以精确计算浮点数的ulp(x)/2,因为浮点除以2是精确的(同样,下溢是被禁止的)。然后你只需要计算x+/-ulp(x)/2的值,适用于较大的浮点类型(如果你对float感兴趣,则为float)或使用BigDecimal类型,并且你有你的interval。我正在用这个解释做一些简化的假设。如果您需要准确说明这一点,请发表评论,我会在有机会时详细说明。另请注意,您问题中的以下陈述:在0.1的情况下,没有用相同位模式表示的低位十进制数是不正确的。您碰巧看到了错误的值(0.999999...而不是0.099999...-一个简单的错字)。Python3.1刚刚实现了这样的功能:查看变更日志(向下滚动一点)、错误报告。以上就是C#学习教程:求内部表示相同的float/double的最小值/最大值。如果对你有用,需要了解更多C#学习教程,希望大家多加关注——本文来自网络收藏,不代表立场,如涉及侵权,请点击有权联系管理员删除。如需转载请注明出处:
