poj-2109

来源:互联网 发布:ubuntu 查看gpu型号 编辑:程序博客网 时间:2024/06/01 14:20
#include <stdio.h>
#include <math.h>
#include <iostream>

using namespace std;

int main() {
    double n, p;
    while(cin>>n>>p) {
        double k = pow(p, 1/n);
        printf("%.0lf\n", k);        
    }

}


C++ AC

对这道题无语了, 开了半天,最后只能痛苦的想到 大数运算(因为10的101次方 long long 都hold不了) 和 折半查找,

然后看了disscuss。。。。

对double(double的精度太NB了)彻底折服了。


有时间看看double的详细格式信息吧(一直对浮点数的格式没具体了解过,没想到这次竟然这么NB)。

http://blog.csdn.net/synapse7/article/details/11672691 一个对double精度适应此题的分析, 基本纯数学了。。

还有 IEEE-754标准来规定浮点数的存储格式。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

目前大多数高级语言(包括C)都按照IEEE-754标准来规定浮点数的存储格式,IEEE754规定,单精度浮点数用4字节存储,双精度浮点数用8字节存储,分为三个部分:符号位、阶和尾数。阶即指数,尾数即有效小数位数。单精度格式阶占8位,尾数占24位,符号位1位,双精度则为11为阶,53位尾数和1位符号位,如下图所示:

单精度浮点数存储格式

31  30        23 22   0

双精度浮点数存储格式

63 62       52 51   0

 

 细心的人会发现,单双精度各部分所占字节数量比实际存储格式都了一位,的确是这样,事实是,尾数部分包括了一位隐藏位,允许只存储23位就可以表示24位尾数,默认的1位是规格化浮点数的第一位,当规格化一个浮点数时,总是调整它使其值大于等于1而小于2,亦即个位总是为1。例如1100B,对其规格化的结果为1.1乘以2的三次方,但个位1并不存储在23位尾数部分内,这个1是默认位。

        阶以移码的形式存储。对于单精度浮点数,偏移量为127(7FH),而双精度的偏移量为1023(3FFH)。存储浮点数的阶码之前,偏移量要先加到阶码上。前面例子中,阶为2的三次方,在单精度浮点数中,移码后的结果为127+3即130(82H),双精度为1026(402H)。

        浮点数有两个例外。数0.0存储为全零。无限大数的阶码存储为全1,尾数部分全零。符号位指示正无穷或者负无穷。

下面举几个例子:

单精度浮点数 十进制规格化符号移阶码尾数                    -12-1.1x23  1100000101000000  00000000  00000000  0.251.0x2-2  0011111010000000  00000000  00000000 

 所有字节在内存中的排列顺序,intel的cpu按little endian顺序,motorola的cpu按big endian顺序排列。

>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>

对于大小为32-bit的浮点数(32-bit为单精度,64-bit浮点数为双精度,80-bit为扩展精度浮点数),
1、其第31 bit为符号位,为0则表示正数,反之为复数,其读数值用s表示;
2、第30~23 bit为幂数,其读数值用e表示;
3、第22~0 bit共23 bit作为系数,视为二进制纯小数,假定该小数的十进制值为x;
十进制转浮点数的计算方法:则按照规定,十进制的值用浮点数表示为:
如果十进制为正,则s = 0,否则s = 1;将十进制数表示成二进制,然后将小数点向左移动,直到这个数变为1.x的形式即尾数,移动的个数即位指数。为了保证指数为正,将移动的个数都加上127,由于尾数的整数位始终为1,故舍去不做记忆。

对3.141592654来说,
1、正数,s = 0;
2、3.141592654的二进制形式为正数部分计算方法是除以二取整,即得11,小数部分的计算方法是乘以二取其整数,得0.0010 0100 0011 1111 0110 1010 1000,那么它的二进制数表示为11.0010 0100 0011 1111 0110 1010 1;
3、将小数点向左移一位,那么它就变为1.1001 0010 0001 1111 1011 0101 01,所以指数为1+127=128,e = 128 = 1000 0000;
4、舍掉尾数的整数部分1,尾数写成0.1001 0010 0001 1111 1011 0101 01,x = 921FB6
5、最后它的浮点是表示为0 1000 0000 1001 0010 0001 1111 1011 0101 = 40490FDA
浮点数转十进制的计算方法:

则按照规定,浮点数的值用十进制表示为:
= (-1)^s  * (1 + x) * 2^(e - 127)

对于49E48E68来说,
1、其第31 bit为0,即s = 0
2、第30~23 bit依次为100 1001 1,读成十进制就是147,即e = 147。
3、第22~0 bit依次为110 0100 1000 1110 0110 1000,也就是二进制的纯小数0.110 0100 1000 1110 0110 1000,其十进制形式为(0.110 0100 1000 1110 0110 1000 * 2^23) / (2^23) = (0x49E48E68 & 0x007FFFFF) / (2^23) = (0x648E68) / (2^23) = 0.78559589385986328125,即x = 0.78559589385986328125。

这样,该浮点数的十进制表示
= (-1)^s  * (1 + x) * 2^(e - 127)
= (-1)^0  * (1+ 0.78559589385986328125) * 2^(147-127)
=    1872333


0 0
原创粉丝点击