-4

我正在尝试反转长双精度数的指数。

假设 x = 3.5e1356。我希望 x 为 3.5e-1356。

我有这个代码:

long double x = 3.5e1356L;
int exponent;
long double fraction = frexpl(x, &exponent);

// recreate number with an inverted exponent
long double newNumber =  ldexpl(fraction, -exponent);

在这段代码之后,newNumber1.14732677619641872902e-1357

这与原始数字无关。

我错过了什么?

4

3 回答 3

3

您已经反转了指数,但指数一开始就不是 1356。long double 的指数是它的二进制指数。

您可能已经写了 3.5 * 10^1356,但在内部,计算机将它存储为 something * 2 ^something else。你所做的是产生一些 * 2^-其他东西,而不是 3.5 * 10^-1356。*

如果您想获得 3.5 * 10^-1356,您可能需要以 10 为底的对数来实现它。

*frexpl 使用与您的计算机可能使用的不同的规范化约定,因此它并没有完全反转机器级指数,而是反转二进制指数而不是您编写的十进制指数。

于 2017-07-15T05:03:48.013 回答
1

利用这个事实

a * (10^n) * (10^m) = a * 10^(n+m) 

如果您计算 m 使其为 -2n,您将得到:

a * (10^n) * (10^-2n) = a * 10^(n+(-2n)) =  a * 10^-n

换句话说 - 只需将原始数字乘以 10^-2n

我会尝试这样的事情:

#include <stdio.h>
#include <math.h>

int main(void) {
    long double x = 8.9e-100;
    long double y = 0.0;
    int exp10;

    if (x != 0.0)
    {
        exp10 = log10l(fabsl(x));
        exp10 = (exp10 >= 0) ? -2*exp10 : -2*(exp10-1);
        y = x * powl(10, exp10);
    }

    printf("%.36Le\n", x);
    printf("%.36Le\n", y);

    return 0;
}

3.5 * 10^12 的示例:

3.5 * 10^12 * 10^-24 --> 3.5 * 10^-12
于 2017-07-15T07:08:10.467 回答
0

根据你们的帮助,我创建了这个有效但可能可以改进的代码......

  NSInteger exponent = 0;
  long double remainder = x;

  // stop the loop if remainder is >= 1 and less than 10
  while (!((fabsl(remainder) >= 1.0L) && (fabsl(remainder) < 10.0L))) {
    remainder /= 10.0L;
    exponent ++;
  }

  long double finalNumber =  remainder * powl(10.0L, -exponent);
于 2017-07-15T05:28:03.757 回答