C 反转长双精度的指数会给我一个疯狂的结果
我试图反转长双精度的指数 假设x=3.5e1356。我希望x是3.5e-1356 我有以下代码:C 反转长双精度的指数会给我一个疯狂的结果,c,floating-point,fractions,exponent,long-double,C,Floating Point,Fractions,Exponent,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); 此代码后的新编号为1
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);
此代码后的新编号为1.14732677619641872902e-1357
那与原来的号码无关
我错过了什么?你倒了指数,但指数一开始就不是1356。长双精度的指数是它的二元指数 您可能编写了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;
}
指数是二进制的,而不是十进制的。请尝试查看实现定义的LDBL_MAX和LDBL_MIN值,即长双精度可以分别表示的最大正值和最小正值。即使是LDBL_MAX的典型值也不超过1E308,而且您的输入值比这个值大得多,所以可能会溢出。一旦发生这种情况,行为就没有定义。需要记住的基本事项:浮点表示不能表示任意大小的值。@彼得:在英特尔硬件上,长双精度有一个16位指数,允许比1E308大得多的数字。@彼得:浮点要求非常保守。OP中的值肯定远远超出了最低要求。但是80位长的double是一种非常常见的实现,它可以追溯到80387 FP协处理器,并且有理由猜测,不需要解释他们正在使用不寻常的硬件的人实际上是在一个具有80位长double的平台上。我不得不问-为什么?你的实验室,2712的10次方在实验误差范围内吗?好的,我现在明白了,但请用答案来说明问题的解决方案,而不是指出问题所在。谢谢我可以想象一个蹩脚的解决方案,其中我创建了一个循环,将x除以10,然后计算除数,直到余数大于等于1且小于10。如果有更好的方法,请解释。@SpaceDog:你知道吗?好的,我可以用它来发现指数,但看看我的答案。。。我看不出这有什么帮助。抱歉,我的大脑没有看到…除法循环会失去精度,而且效率低下,没有什么好的理由,请使用log10l。完美的,我的循环解决方案也很好,但可能会随着循环的进行而失去精度,正如Mateo指出的那样。您在这一行中使用的方法exp10=exp10>=0-2*exp10:-2*exp10-1;,将整个事物乘以相反的东西,这很有趣。感谢可能并不完美。角盒:exp10=log10lfabslx;当x==0.0.exp10=exp10>=0时出现问题-2*exp10:-2*exp10-1;y=x*powl10,exp10;招致不必要的溢出。。可以使用两个步骤:exp10=exp10>=0-exp10:-exp10-1;y=x*powl10,exp10*powl10,exp10;
3.5 * 10^12 * 10^-24 --> 3.5 * 10^-12