双精度转换为科学记数法 - 精度误差
double to scientific notation conversion - precision error
我正在编写一段代码,以在 C++ 中将双精度值转换为精度高达 15 的科学记数法。我知道我可以使用带有 %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所以我们得到这个结果)
预期答案:norm = 6.860 000 000 000 000,exp = 7
我的问题是,是否有更好的方法将双精度转换为科学记数法,精度为 15(不使用标准库),以便在四舍五入时得到准确的 6.86。如果您注意到这里的问题不是舍入机制,而是由于与机器 epsilon
相关的精度损失导致的双精度到科学记数法的转换
您可以将 norm 声明为 long double 以获得更高的精度。 long double wiki 尽管有一些特定于编译器的问题需要注意。一些编译器使 long double 成为 double 的同义词。
解决此精度问题的另一种方法是使用字符串形式的数字,并为不受机器 epsilon 影响的字符串实施自定义算术运算。
例如:
int getEXP(string norm){ return norm.length() - 1; };
string norm = "68600000";
int exp = getEXP(norm); // returns 7
下一步将是实现将小数点字符插入标准字符串中适当位置的函数,并添加您想要的任何精度级别。无需担心机器 epsilon。
我正在编写一段代码,以在 C++ 中将双精度值转换为精度高达 15 的科学记数法。我知道我可以使用带有 %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所以我们得到这个结果)
预期答案:norm = 6.860 000 000 000 000,exp = 7
我的问题是,是否有更好的方法将双精度转换为科学记数法,精度为 15(不使用标准库),以便在四舍五入时得到准确的 6.86。如果您注意到这里的问题不是舍入机制,而是由于与机器 epsilon
相关的精度损失导致的双精度到科学记数法的转换您可以将 norm 声明为 long double 以获得更高的精度。 long double wiki 尽管有一些特定于编译器的问题需要注意。一些编译器使 long double 成为 double 的同义词。
解决此精度问题的另一种方法是使用字符串形式的数字,并为不受机器 epsilon 影响的字符串实施自定义算术运算。 例如:
int getEXP(string norm){ return norm.length() - 1; };
string norm = "68600000";
int exp = getEXP(norm); // returns 7
下一步将是实现将小数点字符插入标准字符串中适当位置的函数,并添加您想要的任何精度级别。无需担心机器 epsilon。