- 数据结构编程实验(第3版)
- 吴永辉 王建德编著
- 1397字
- 2021-08-13 17:23:58
1.3 在实数和整数之间转换
程序设计语言的基本数据类型有整数型、实数型、字符型等。有些试题的数据对象是实数和整数,并且要进行实数和整数之间的转换运算。
【1.3.1 I Think I Need a Houseboat】是实数向整数转换的实验范例,【1.3.2 Integer Approximation】则是在整数运算过程中产生实数的实验范例。
【1.3.1 I Think I Need a Houseboat】
Fred Mapper计划在Louisiana购买一块土地,并在这块土地上建造他的家。在对土地调查后,他发现,由于Mississippi河的侵蚀,Louisiana州的土地每年减少50平方英里。因为Fred准备在他所建的家中度过后半生,所以他要知道他的土地是否会因为河流的侵蚀而消失。
在做了大量研究后,Fred发现正在失去的土地构成一个半圆形(半圆如图1.3-1所示)。这一半圆形是一个圆的一部分,圆心在(0,0),二等分这个圆的线是x轴,x轴的下方是河水。在第1年开始的时候,这个半圆的面积为0。
图 1.3-1
输入
输入的第一行是一个正整数,表示有多少个测试用例(N)。后面有N行,每行给出笛卡儿坐标x和y,表示Fred考虑购买的土地的位置。这些数是浮点数,以英里为单位。y坐标非负。不会给出坐标(0,0)。
输出
对每个输入的测试用例,输出一行。这一行的形式为“Property N:This property will begin eroding in year Z.”,其中N是测试用例编号(从1开始记数),Z表示Fred的土地在第Z年结束的时候要落到半圆形中(从1开始记数),Z必须是一个整数。在最后一个测试用例后,输出“END OF OUTPUT.”。
说明
1)购买的土地不会在半圆形的边界上,它或者落在半圆形内,或者位于在半圆形外。
2)这一问题被自动裁判,所以输出要精确匹配,包括大小写、标点符号和空格,以及到行末的完整的句子。
3)所有的地点都以英里为单位。
试题来源:ACM Mid-Atlantic 2001
在线测试:POJ 1005,ZOJ 1049,UVA 2363
试题解析
由于测试用例的个数N预先确定,且每个测试用例是笛卡儿坐标,因此可直接采用for循环处理所有测试用例。第i个测试用例(xi,yi)与圆心(0,0)构成的半圆面积即土地被河流侵蚀的范围。由于每年减少50平方英里土地,而年份是整数,因此淹没(xi,yi)的年份应为大于的最小整数,这个取整过程应使用向上取整函数ceil(x)。若使用向下取整函数floor(x),则会提前1年失去土地。
参考程序
#include <stdio.h> //预编译命令 #include <math.h> #define M_PI 3.14159265 int num_props; //定义测试用例数为整数 float x, y; //定义笛卡儿坐标为单精度实数 int i; double calc; //定义半圆面积/50为双精度实数 int years; //定义失去土地的年份为整数 int main(void) //主函数 { //主函数开始 scanf("%d", &num_props); //输入测试用例数 for (i = 1; i <= num_props; i++) { scanf("%f %f", &x, &y); //输入第i个考虑购买的土地位置,计算和输出半圆面积/50 //(向上取整后即土地失去的年份) calc = (x*x + y*y)* M_PI / 2 / 50; years = ceil(calc); printf("Property %d: This property will begin eroding in year %d.\n", i, years); } printf("END OF OUTPUT.\n"); }
【1.3.2 Integer Approximation】
FORTH程序设计语言不支持浮点数的算术运算。它的发明者Chuck Moore坚持认为浮点数的运算太慢,而且在大多数时候都可以用适当的整数比来仿真浮点数。例如,要计算半径为R的圆的面积,他建议使用R×R×355/113这一公式,这实际上是非常精确的。整数比355/113≈3.141593是π的近似值,绝对值误差约为2×10-7。给出一个浮点数A和一个整数限制L,请找出在范围[1,L]内的两个整数N和D(1≤N,D≤L),使得N和D的比是A的最佳整数近似,即找到绝对值误差|A-N/D|最小的两个整数N和D。
输入
输入的第一行给出浮点数A(0.1≤A<10),精度达15位小数。第二行给出整数限制L(1≤L≤100000)。
输出
输出给出两个用空格分隔的整数:N和D。
试题来源:ACM Northeastern Europe 2001,Far-Eastern Subregion
在线测试:POJ 1650
试题解析
本题采用“追赶法”,在分子和分母不超过整数限制的前提下不断枚举a和b。设最小绝对值误差为Min,整数限制为n。初始时取a、b为1,Min为n+1;然后每次对a、b求商,调整Min:
·在a/b>x的情况下,若a/b-x小于Min,则Min调整为a/b–x,记录下此时的a和b值;为了使下一次枚举时的a/b更趋近x,b增加1。
·在a/b≤x的情况下,若x-a/b小于Min,则Min调整为x-a/b,记录下此时的a和b值;为了使下一次枚举时的a/b更趋近x,a增加1。
本题处理的数据是精度达15位小数的浮点数,因此变量x、a、b、n和Min采用双精度类型。
参考程序
#include <stdio.h> int main() { double x, a, b, n, Min, n1, n2; //浮点数x,整数限制n,当前分母和分子为a和b,绝对值的最 //小误差为Min,绝对值误差为Min时的分母和分子为n1和n2 scanf("%lf%lf", &x, &n); //输入浮点数x和整数限制n a = 1; //绝对值误差最小的两个整数初始化 b = 1; Min = n + 1; //最小误差值初始化 while(a <= n && b <= n) //若两个整数未超过限制 { if (a / b > x) //若a/b在数轴上位于x右方且与x的距离值目前最小, //则记下a和b并将a/b – x调整为最小绝对值误差 { if (a / b - x < Min) { Min = a / b - x; n1 = a; n2 = b; } b++; //增大分母b,使a/b更趋近x } //若在数轴上,a/b位于x左方且与x的距离值目前最小,则记下a和b并将x-a/b调整为最小绝对值误差 else { if (x - a / b < Min) { Min = x - a / b; n1 = a; n2 = b; } a++; //增大分子a,使a/b更趋近x } } printf("%.0f %.0f\n", n1, n2); //输出绝对值误差|x-n1/n2|最小的n1和n2 return 0; }