反转 long double 的指数给我一个疯狂的结果

Inverting the exponent of a long double gives me an insane result

我正在尝试反转 long double 的指数。

假设 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);

在这段代码之后,newNumber就是1.14732677619641872902e-1357

与原号码无关

我错过了什么?

你倒转了指数,但指数一开始就不是 1356。 long double 的指数是它的 binary 指数。

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

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

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

在你们的帮助下,我创建了这段代码,它可以正常工作,但可能还可以改进...

  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);

利用

这一事实
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