双倍到科学记数法转换 - 精度误差

double to scientific notation conversion - precision error

本文关键字:转换 精度 误差      更新时间:2023-10-16

我正在编写一段代码,将双精度转换为科学记数法,精度高达 15 英寸C++。我知道我可以使用带有 %e 选项的 sprintf 等标准库来执行此操作。但我需要拿出自己的解决方案。我正在尝试这样的事情。

double norm = 68600000;
if (norm)
{
    while (norm >= 10.0)
    {
      norm /= 10.0;
      exp++;
    }
    while (norm < 1.0)
    {
      norm *= 10.0;
      exp--;
    }
}

我得到的结果是

norm = 6.8599999999999994316;
exp = 7

失去这种精度的原因我从这个问题中澄清了

现在我尝试将值舍入到精度 15,这将导致

6.859 999 999 999 999

(很明显,由于小数点第 16 位小于 5,我们得到这个结果)

预期答案:标准 = 6.860 000 000 000 000,exp = 7

我的问题是,有没有更好的方法将双倍到科学记数法转换为 15 的精度(不使用标准库),这样当我四舍五入时我会得到正好 6.86。如果您已经注意到这里的问题不在于舍入机制,而在于由于与机器 epsilon 相关的精度损失而导致的双倍到科学记数法转换

您可以将规范声明为长双精度,以获得更高的精度。 长双维基 尽管有一些编译器特定的问题需要注意。一些编译器将长双精度与双精度同义。

解决此精度问题的另一种方法是处理字符串形式的数字,并为不受机器 epsilon 影响的字符串实现自定义算术运算。例如:

int getEXP(string norm){ return norm.length() - 1; };
string norm = "68600000";
int exp = getEXP(norm); // returns 7

下一步是实现函数,将十进制字符插入规范字符串中的适当位置,并添加所需的任何精度级别。无需担心机器 epsilon。