请问😣最高有效位为符号位,3位余码表示的指数域以及4位尾数,下面哪个数值不能用8位浮点格式准确地存储?

求详细解答这种题到底是怎么做的,为什么不能被准确存储啊,思路是什么。救救孩子吧

img

a和d应该都不行吧

这道题应该选A。
先回答一下题主说的为什么不能准确存储的问题,因为计算机底层数字都是2进制表示的,有些数字就是不能准确表示只能无线逼近,不过一般都遵循IEEE 754标准。

img

当看到指数、尾数这些关键字,说明是使用科学计数法。思路就是慢慢调参数,高了就把指数、尾数降低一点,低了就提高,提高到最大精度了还是不相等,答案就是他了。幸亏出题人给出的位数不高,不然要算死我啊,思路就贴图吧:

img


有啥不懂的题主可以继续问,我感觉没讲清楚...

先大致说明一下 8位浮点数表示法,详细内容搜索IEEE754规范,并仔细阅读。

/// +----+-----------+----------------+
/// + b7 |  b6 b5 b4 | b3  b2  b1  b0 |
/// +sign|    exp    |    mantissa    |
/// +----+-----------+----------------+

这里的符号位是最高位:0为正,1为负
指数位,阶码,3位:注意要减去4,000表示-4,111表示3,IEEE754规范里还有点不同
小数位,4位:按IEEE754规范,隐含着1.0

程序员,得用编程的思路解决这道题,我写了一个C#程序:

public struct MiniFloat
{
    public int sign; // 符号位,0为正,1为负
    public int e; // [-4, 3]
    public int m; // [0, 15]

    public MiniFloat(int s, int e, int m)
    {
        this.sign = s;
        this.e = e;
        this.m = m;
    }

    public MiniFloat(int binary)
    {
        this.sign = (binary & 0x80) >> 7;
        this.e = ((binary & 0x70) >> 4) - 4; // 3位阶码,表示范围为0到7,减去4后,表示范围为-4到3
        this.m = binary & 0x0F; // 后4位
    }

    public double GetValue()
    {
        return (sign == 0 ? 1 : -1) * CompMantissa(m) * Math.Pow(2, e);
    }

    public override string ToString()
    {
        string s = string.Format("值:{0},指数部分:{1},小数部分:{2},二进制表示:{3}", GetValue(), e, m, BinaryString());
        return s;
    }

    public string GetDetails()
    {
        StringBuilder sb = new StringBuilder();
        sb.AppendLine("数值:" + GetValue());
        sb.AppendLine("二进制表示:" + BinaryString());
        sb.AppendLine("小数部分(二进制):1." + Convert.ToString(m, 2).PadLeft(4, '0'));
        double manti = MiniFloat.CompMantissa(this.m);
        sb.AppendLine("小数部分(十进制):" + manti);
        sb.AppendLine("阶码:" + this.e);
        sb.AppendLine(GetValue() + " = " + manti + " * (2 ^ " + this.e + ")");
        return sb.ToString();
    }

    public string BinaryString()
    {
        return Convert.ToString((sign << 7 | ((e + 4) & 0x7) << 4) | m, 2).PadLeft(8, '0');
    }

    static public double CompMantissa(int bits)
    {
        double[] v = { 0.5, 0.25, 0.125, 0.0625 };
        double mantissa = 1.0; // IEEE754规定小数部分都是1.0开始
        for (int i = 0; i < v.Length; i++)
        {
            if ((bits & 0x08) != 0)
            {
                mantissa += v[i];
            }
            bits = bits << 1;
        }
        return mantissa;
    }
}


主程序这样:

static void Main(string[] args)
{
    double[] arr = { 6.25, 7, 2.5, 0.1875 };
    foreach (double f in arr)
    {
        MiniFloat a = TryMiniFloat(f);
        Console.WriteLine(a.GetDetails());
    }
    Console.ReadLine();
}

static MiniFloat TryMiniFloat(double f)
{
    double eps = 999.0;
    MiniFloat mini = new MiniFloat { };
    for (int i = 0; i < 256; i++)
    {
        MiniFloat temp = new MiniFloat(i);
        double approx = temp.GetValue();
        if (Math.Abs(approx - f) < eps)
        {
            eps = Math.Abs(approx - f);
            mini = temp;
        }
    }
    return mini;
}

运行结果是这样的:
数值:6.25
二进制表示:01101001
小数部分(二进制):1.1001
小数部分(十进制):1.5625
阶码:2
6.25 = 1.5625 * (2 ^ 2)

数值:7
二进制表示:01101100
小数部分(二进制):1.1100
小数部分(十进制):1.75
阶码:2
7 = 1.75 * (2 ^ 2)

数值:2.5
二进制表示:01010100
小数部分(二进制):1.0100
小数部分(十进制):1.25
阶码:1
2.5 = 1.25 * (2 ^ 1)

数值:0.1875
二进制表示:00011000
小数部分(二进制):1.1000
小数部分(十进制):1.5
阶码:-3
0.1875 = 1.5 * (2 ^ -3)

所以按照IEEE754规范,这四个浮点数都可以表示出来。
但如果小数部分不隐含着1.0,那么6.25表示不出来,答案只能选A。

如果不用编程来解这道题,只能把这个数值不停地乘或除2,看能否用0.5, 0.25, 0.125, 0.0625凑出来,阶码还在控制在[-4,3]之间。

用了几个小时写的C#程序,专门 解决这道题,如果有用请采纳。