C# 查找具有相同内部表示形式的浮点/双精度浮点的最小值/最大值

C# 查找具有相同内部表示形式的浮点/双精度浮点的最小值/最大值,c#,.net,floating-point,bit-manipulation,ieee-754,C#,.net,Floating Point,Bit Manipulation,Ieee 754,更新IEEE-754并参与其中,让我想到了tinker:如何获得二进制表示相等的给定浮点数的最大值和最小值 免责声明:在本次讨论中,我喜欢坚持使用IEEE-754中描述的32位和64位浮点。我对扩展浮点(80位)或四进制(128位IEEE-754-2008)或任何其他标准(IEEE-854)不感兴趣 背景:计算机不擅长用二进制表示法表示0.1。在C#中,浮点数在内部表示为3dccccd(C#使用四舍五入到最近值),双精度表示为3fb9999999a。相同的位模式用于十进制0.100000005(

更新IEEE-754并参与其中,让我想到了tinker:如何获得二进制表示相等的给定浮点数的最大值和最小值

免责声明:在本次讨论中,我喜欢坚持使用IEEE-754中描述的32位和64位浮点。我对扩展浮点(80位)或四进制(128位IEEE-754-2008)或任何其他标准(IEEE-854)不感兴趣

背景:计算机不擅长用二进制表示法表示
0.1
。在C#中,浮点数在内部表示为
3dccccd
(C#使用四舍五入到最近值),双精度表示为
3fb9999999a
。相同的位模式用于十进制
0.100000005
(浮点)和
0.10000000000000124
(双精度),但不用于
0.10000000000000144
(双精度)

为方便起见,以下C#代码给出了这些内部表示:

string GetHex(float f)
{
    return BitConverter.ToUInt32(BitConverter.GetBytes(f), 0).ToString("X");
}

string GetHex(double d)
{
    return BitConverter.ToUInt64(BitConverter.GetBytes(d), 0).ToString("X");
}

// float
Console.WriteLine(GetHex(0.1F));

// double 
Console.WriteLine(GetHex(0.1));
0.1
的情况下,没有用相同的位模式表示的较低的十进制数,任何
0.99…99
将产生不同的位表示(即
0.999999937
内部产生
3F7FFFFF

我的问题很简单:如何找到内部存储在相同二进制表示形式中的给定浮点(或双精度)的最低和最高十进制值

为什么:(我知道你会问)查找.NET转换为字符串和从字符串转换时的舍入错误,查找内部精确值并更好地理解我自己的舍入错误


我的猜测是这样的:取尾数,去掉剩下的,得到它的精确值,再高一个(尾数),然后计算平均值:任何低于尾数的值都会产生相同的位模式。我的主要问题是:如何将分数部分转换为整数(位操作不是我最强大的资产)。上课可能会有帮助。

解决问题的一种方法是在浮点数的Lastp区域中找到ULP或Unit的大小。稍微简化一下,这是给定浮点数与下一个较大数之间的距离。同样,简化一点,给定一个可表示的浮点值x,任何值介于(x-1/2 ulp)和(x+1/2 ulp)之间的十进制字符串在转换为浮点值时都将四舍五入到x

诀窍在于(x+/-1/2 ulp)不是一个可表示的浮点数,因此实际计算其值需要使用更宽的浮点数类型(如果有)或任意宽度的大小数或类似类型来进行计算

您如何找到ulp的大小?一个相对简单的方法大致就是你所建议的,这里写的是C-ish伪代码,因为我不懂C#:


这是因为向x的位模式添加一个正好对应于向x的值添加一个ulp。减法中不会出现浮点舍入,因为所涉及的值非常接近(特别是,ieee-754浮点运算的一个定理是,如果两个数字x和y满足y/2Python 3.1刚刚实现了如下内容:看,。

很好的答案,似乎就是我要找的信息。我会尝试用C#来解决这个问题,如果我需要更多关于花边的帮助,请回到这里。我注意到你在h IEEE-754团队来建立这个标准?我很荣幸:)。你在这个错误上说得很对!我很惊讶我找不到一个更低的值,但我认为这是理所当然的,并把它写下来,错误和所有的,哈哈!
float absX = absoluteValue(x);
uint32_t bitPattern = getRepresentationOfFloat(absx);
bitPattern++;
float nextFloatNumber = getFloatFromRepresentation(bitPattern);
float ulpOfX = (nextFloatNumber - absX);