1. 程式人生 > >UVA ~ 11809 ~ Floating-Point Numbers (數學,思維)

UVA ~ 11809 ~ Floating-Point Numbers (數學,思維)

在這裡插入圖片描述
在這裡插入圖片描述

題意

在這裡插入圖片描述

思路

假設該數字表示為X2YX*2^Y,那我們要求解的就是X2Y=A10BX*2^Y=A*10^B,M=(X的位數),E=(Y的位數)
如果直接去計算這個數字的話會很大,因為Y有30位長,這個數大概也就是210302^{10^{30}}肯定是會炸的,所以想辦法把這個數字去縮小一下,很容易想到使用loglog取對數的方式。
log10(X2Y)=log10(A10B)log_{10}(X*2^Y)=log_{10}(A*10^B) =>
log10(X)+Ylog102=log10(A)+Blog_{10}(X)+Y*log_{10}2=log_{10}(A)+B


因為題目中說這個數是一個尾碼長度為為M,階碼長度為E最大的浮點數,那麼Y=2E1Y=2^E-1
X=21+22++21MX = 2^{-1} + 2^{-2} + … + 2^{-1-M} => X=121MX = 1-2^{-1-M}
我們通過列舉答案 M 和 E 求得 X 和 Y ,如果符合log10(X)+Ylog102=log10(A)+Blog_{10}(X)+Y*log_{10}2=log_{10}(A)+B,那麼就是答案。

注意可能會有精度損失,所以判斷兩個數字相等的時候不能直接用==,而是當誤差小於某個值時就認為相等。

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const double eps = 1e-7;
int main()
{
    char s[30];
    while (~scanf("%s%*c", s) && strcmp(s, "0e0") != 0)
    {
        LL A = s[0]-'0', B = 0;
        for
(int i = 2; i < 17; i++) A = A*10+s[i]-'0'; for (int i = 18; i < strlen(s); i++) B = B*10+s[i]-'0'; double t = log10(A)+B-15; bool flag = false; for (int i = 0; i < 10; i++) { for (int j = 1; j <= 30; j++) { double X = 1 - pow(2, -1-i), Y = pow(2, j)-1; double ans = log10(X)+Y*log10(2); if (fabs(ans - t) < eps) { flag = true; printf("%d %d\n", i, j); break; } } if (flag) break; } } return 0; } /* 5.699141892149156e76 9.205357638345294e18 0e0 */