算法竞赛入门经典(紫书)第三章——Floating-Point Numbers UVA-11809

本文详细解析了一种特定浮点数存储机制的工作原理,包括如何通过尾数和阶码来确定最大数值,并通过数学推导及编程实现,提供了一个有效的解决方案来找出对应的尾数位数(M)和阶码位数(E)。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题意:
题目介绍了浮点数存储的方法,尾数有 M 位,阶码有 E 位,还有两位符号位分别表示尾数的符号和阶码的符号。现在给出对应一种 M 和 E 的能够表示的最大数,要求判断出 M 和 E 的值,其中 M 属于 (0, 9),E 属于 (1, 30)。

思路:
题目的 Input 中说有 300 行输入,且 M 属于 (0, 9),E 属于 (1, 30),刚好有 300 种情况,我们会去朝着打表的方向去想。
我们先将对应 M 和 E 的浮点数最大值求出来,如下图,浮点数最大值的二进制形式应该是这样的。

换算成十进制的数应该是
(2M+11)×22EM2 ( 2 M + 1 − 1 ) × 2 2 E − M − 2
=2M+1×22EM222EM2 = 2 M + 1 × 2 2 E − M − 2 − 2 2 E − M − 2
=22E122EM2 = 2 2 E − 1 − 2 2 E − M − 2
=22E1×(12M1) = 2 2 E − 1 × ( 1 − 2 − M − 1 )

又 题目的输入是 A×10B A × 10 B ,所以有
A×10B=22E1×(12M1) A × 10 B = 2 2 E − 1 × ( 1 − 2 − M − 1 )

我们希望的是事先通过打表算出上面等式的右边部分,然后和输入的数据,即左边部分进行比较找到 A 和 B。
但是现在的左边部分太大了,比如样例一就有 10 的 76 次方多了,所以还得另想办法。
用数学的办法,我们将等式两边取对数,得到
lgA+B=lg22E1+lg(12M1) l g A + B = l g 2 2 E − 1 + l g ( 1 − 2 − M − 1 )
lgA+B=(2E1)×lg2+lg(12M1) ⇒ l g A + B = ( 2 E − 1 ) × l g 2 + l g ( 1 − 2 − M − 1 )

有了上面的等式,我们就可以打表啦

注意:
1.如果读取数据时用 double 型读取,读取不到 A 和 B,所以我们选择把输入当成字符串读取,然后处理出 A 和 B。
2. lg 的函数应该是 log10(),不是 log()。log() 函数是 ln。我就在这弄错了。
3. 浮点数的比较要取绝对值然后和较小的一个数比较,这里用的是 1e-4。

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<stack>
#include<queue>
#include<utility>
#include<vector>
#include<cmath>
#include<set>
#include<map>
#include<iostream>
#include<algorithm>
#include<sstream>
using namespace std;
typedef long long LL;

char ch[30];
double A;
double B;
double num[15][35];

int main()
{
    //freopen("in.txt", "r", stdin);
    //初始化数据
    for(int M=0; M<=9; M++){
        for(int E=1; E<=30; E++){
            num[M][E] = (pow(2, E)-1)*log10(2) + log10(1-pow(2, -M-1));
            //printf("M = %d, E = %d, num = %.15lf\n", M, E, num[M][E]);
        }
    }
    while(scanf("%s", ch)==1 && strcmp(ch, "0e0")!=0){
        //输入处理
        A = B = 0;
        int len = strlen(ch);
        int i = 0;
        for(; ch[i]!='.'; i++){
            A *= 10;
            A += ch[i]-'0';
        }
        i++;
        for(double w = 1; ch[i]!='e'; i++){
            w /= 10;
            A += w*(double)(ch[i]-'0');
        }
        i++;
        for(; i<len; i++){
            B *= 10;
            B += ch[i]-'0';
        }

        //printf("%.15lfe%.15lf\n", A, B);
        double C = B+log10(A);
        //printf("C = %.15lf\n", C);
        bool ok = false;
        for(int i=0; i<=9; i++){
            for(int j=1; j<=30; j++){
                if(fabs(C-num[i][j]) < 1e-4){
                    ok = true;
                    printf("%d %d\n", i, j);
                    break;
                }
            }
            if(ok) break;
        }
    }
    return 0;
}

想看书上的源代码的话看这 (^▽^)
https://github.com/aoapc-book/aoapc-bac2nd

### MATLAB 输入参数必须可转换为浮点数的解决方案 当遇到 `input arguments must be convertible to floating-point numbers` 错误时,通常是因为传递给函数的参数不是有效的数值类型。为了修复此问题,可以采取以下几种方法: #### 1. 检查数据类型 确保所有输入变量都是数值型或能够被转换成双精度浮点数 (double) 类型的数据。可以通过 `class()` 函数来验证变量的具体类别。 ```matlab if ~isnumeric(x) || ~isa(x, 'double') error('Input argument ''x'' is not a valid numeric type.'); end ``` 如果发现某些变量并非预期中的数值形式,则应先将其转换再继续操作[^1]。 #### 2. 使用 str2double 进行字符串到数字的转换 对于由字符组成的数组或其他非标准格式存储起来的实际数值,在调用目标函数之前应当尝试利用内置命令如 `str2double()` 来完成必要的转型工作。 ```matlab y = str2double(str); % 如果 y 返回 NaN 表明无法成功解析该串成为合法实数 if isnan(y) warning('Conversion failed'); else disp(['Converted value:', num2str(y)]); end ``` #### 3. 处理缺失值与异常情况 有时也会因为存在未定义元素(NaN)、无穷大(Inf)等原因而触发上述报错提示;因此建议提前过滤掉这些特殊情形下的记录项后再执行后续计算逻辑。 ```matlab data(isnan(data)) = 0; % 将所有的 NaN 替换成零 data(~isfinite(data)) = 0;% 或者处理其他类型的非法数值 ``` 通过以上措施一般能有效规避因不当传参所引发的相关运行期错误消息显示出来[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值