列表

详情


NC212856. 鸽子的浮点运算

描述

众所周知金⻥的记忆只有七秒,而鸽子们的记性也不太好(不然怎么会经常放别人鸽子),所以对于鸽子们来说32位的浮点数运算太难了,所以他们发明了一种新的浮点数表示方式,他们称之为16位浮点。
而开学前的最后一天某位不愿透露姓名的陈XX鸽子突然跑来找你,想让你帮他解决他的假期作业,你看到这个厚达 1e9+7⻚的作业,陷入了沉思,机智的你很快就想到用程序去批量完成它。
现在作业里面有这么些题型:
1.将 一个小数转成16位浮点数,然后输出它的的二进制表示 
2.将两个浮点数分别转成16位浮点数然后相加,然后输出答案的二进制表示 
3.将两个浮点数分别转成16位浮点数然后相乘,然后输出答案的二进制表示 

接下来就是简单的介绍一下什么是16位浮点: 
上图是16位浮点的机内表示,接下来以十进制数 7.625 举例跟32位浮点类似,16位浮点分为3个组成部分:
最高位S(第15位):符号位,1为负,0为正,7.625是正数所以最高位为0 
第14位~第10位 E:带偏移的指数,偏移量为15,如7.625的二进制表示为 111.101也可以表示为1.11101 * (2^2), 所以应该为15+2=17=10001 
第9位~第0位 M:为数据位,就是数据的表示,不过这里记载的是用二进制的科学计数法表示后的数据小数点 后的部分,如7.625可以表示为二进制科学计数法的1.11101 * (2^2),那么他的数据位就是.11101,小数点在计算 机内省略故最后7.625的16进制表示为0100011110100000 
注:如果原始数据或者运算中间数据太⻓时采用截断的方式,如,某浮点数数据位原来为 .1111111111111111111111,那么转16位时,只保留10位为.1111111111,如果是运算中间过程时是先运算再截断

输入描述

第一行一个数字T表示组数
接下来T行,每一行包括一个整数op(),以及两个浮点数a,b,op代表操作类型,具
体操作与题目表述中一致。
当op为1时,题目保证a==b,输出的答案也为a,b任一的二进制表示(因为两数相同)
当op为2时,输出的答案为a,b先转16位浮点后,再进行加法运算后结果的二进制进制表示
当op为3时,输出的答案为a,b先转16位浮点后,再进行乘法运算后结果的二进制表示

输出描述

⻅题目表述 
注:前导零不能省略

示例1

输入:

3
1 7.625 7.625
2 7.625 7.625
3 7.625 7.625

输出:

0100011110100000
0100101110100000
0101001101000100

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 6ms, 内存消耗: 396K, 提交时间: 2020-10-27 14:02:00

#include<bits/stdc++.h>
#define LL long long
using namespace std;
LL opt;
float al,be;
int T;
LL ch(float x)
{
	LL *y=(LL*)(&x);
	return *y;
}
float rh(LL x)
{
	float *y=(float*)(&x);
	return *y;
}
int main()
{
	cin>>T;
	while(T--)
	{
		scanf("%lld%f%f",&opt,&al,&be);
		LL x=ch(al);
		x&=(((1<<19)-1)<<13);
		al=rh(x);
		x=ch(be);
		x&=(((1<<19)-1)<<13);
		be=rh(x);
		if(opt==2)
		{
			al+=be;
		}
		if(opt==3)
		{
			al*=be;
		}
		x=ch(al);
		LL y=((x>>23)-127+15)<<10;
		x&=(((1<<10)-1)<<13);
		x>>=13;
		y+=x;
		for(LL i=15;i>=0;--i)
		{
			printf("%lld",(y&(1<<i))>>i);
		}
		printf("\n");
	}
	return 0;
}

上一题