C语言 反转长双精度的指数给了我一个疯狂的结果



我试图反转长双精度的指数。

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

这与原始号码无关。

我错过了什么?

您已经反转了指数,但指数从一开始就不是 1356。长双精度的指数是其二进制指数。

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

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

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

使用以下事实

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("%.36Len", x);
printf("%.36Len", y);
return 0;
}

3.5 * 10^12的示例:

3.5 * 10^12 * 10^-24 --> 3.5 * 10^-12

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

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

最新更新