将字符串格式化为科学计数法

Posted

技术标签:

【中文标题】将字符串格式化为科学计数法【英文标题】:Format string into scientific notation 【发布时间】:2009-12-29 19:31:16 【问题描述】:

我有一个如下所示的字符串:

"0.4794255386042030002732879352156"

这大约是 sin(0.5)。我想格式化字符串看起来更好

"4.794255386042e-1"

我怎样才能做到这一点?请记住,我处理的是字符串而不是数字(浮点数、双精度数)。另外我需要四舍五入以保持数字尽可能准确,我不能只是截断。如果我需要转换为不同的数据类型,我会更喜欢 long double,因为常规的 double 没有足够的精度。我希望在四舍五入之前至少有 12 位小数。也许我可以做一个简单的 sprintf() 转换。

【问题讨论】:

【参考方案1】:

类似这样的:

#include<iostream>
using namespace std;

int main()

        char *s = "0.4794255386042030002732879352156";
        double d;

        sscanf(s,"%lf",&d);
        printf("%.12e\n",d);

        return EXIT_SUCCESS;

输出:

# g++ a.cpp  && ./a.out
4.794255386042e-01

【讨论】:

【参考方案2】:

您在寻找类似this 的东西吗?

这是一个示例:

 // modify basefield
#include <iostream>
#include <sstream>

using namespace std;

int main () 
    std::string numbers("0.4794255386042030002732879352156");
    std::stringstream stream;
    stream << numbers;
    double number_fmt;
    stream >> number_fmt;
    cout.precision(30);

    cout << number_fmt << endl;

    cout.precision(5);
    cout << scientific << number_fmt << endl;
  return 0;

输出:

0.479425538604203005377257795772

4.79426e-01

【讨论】:

【参考方案3】:

在高度便携的C 中,下面的工作示例输出:

result is 4.794255386042E-01


#include <stdio.h>

int main()

    char *str = "0.4794255386042030002732879352156";

    double f;
    char   newstr [50];
    // convert string in `str` to float
    sscanf (str, "%le", &f);

    sprintf (newstr, "%.12E", f);
    printf ("result is %s\n", newstr);
    return 0;

【讨论】:

【参考方案4】:

查看问题中的字符串,您似乎正在使用以 10 为底的对数。在那种情况下,通过直接扫描字符串来计算前导或尾随零并将其放入指数中不是相对容易吗?

也许我错过了什么..

【讨论】:

同意。在这种情况下,他可以简单地找到该点的位置,移动它,并附加指数作为该点移动的距离和方向的计数。【参考方案5】:

IEEE 754 64 位浮点数(即双精度)适用于 15 位十进制有效数字,因此转换为双精度数应该没有问题。您更有可能遇到让格式说明符显示所有可用数字的问题。尽管从发布的示例来看,情况似乎并非如此。

【讨论】:

你说得对,一旦我添加了正确格式的字符串,双精度就足够了,我什至从双精度中得到了 17 个十进制数字,我相信我可以得到更多,但这已经足够了。 没有双倍你不能!事实上,无论你得到什么,即使是 17 也是不可能的。尾数是 52 位,2^52 是 16 位十进制数,因此限制为 15 位(数学上为 15.65 位),因为 52 位足以表示所有可能的 15 位数字。请注意,我说的是重要数字而不是小数位。【参考方案6】:

使用sscanf() 转换为long double,然后使用sprintf() 使用科学格式化程序将其作为字符串打印出来:

long double x;
char num[64];

if(sscanf(string, "%Lf", &x) == 1)
  sprintf(num, "%.12Le", x);

但不确定long double 是否真的给了你 12 位有效数字。在我的系统上,这会生成"4.79425538604e-01"

【讨论】:

你的意思是 if(sscanf(string, "%Lf", &x) == 1) 因为 %Ld 给出一个长整数?【参考方案7】:

在 C 或 C++ 中都没有标准函数可以做到这一点。通常的做法是要么转换成数字(然后使用标准函数来格式化数字),要么编写自己的自定义输出函数。

【讨论】:

【参考方案8】:
#include <iostream>
using namespace std;
...
double dd = strtod( str );
cout << scientific << dd << endl;

【讨论】:

不,输出 0.4794255386042030002732879352156,这不是他要求的。 不,它输出 4.794255e-01 (默认精度为 6 )。 'cout.precision(12)' 会将其设置为 12。【参考方案9】:

根据您想要的小数位数(在本例中为 12 个),您可以执行以下操作:

int main()  
  char buff[500];
  string x = "0.4794255386042030002732879352156";
  double f = atof(x.c_str());
  sprintf(buff,"%.12fe-1",f*10);
  cout<<buff<<endl;
  return 0;

结果: ---------- 捕获输出 ----------

"c:\windows\system32\cmd.exe" /c c:\temp\temp.exe 4.794255386042e-1 以退出代码 0 终止。

【讨论】:

以上是关于将字符串格式化为科学计数法的主要内容,如果未能解决你的问题,请参考以下文章

将数字格式化为科学计数法,但使用 3e-5 而不是 3e-05

将 y 轴标签格式化为具有许多零的更高千位科学记数法?

将 C# Double 格式化为以三的倍数为单位的科学记数法

excel中长数字字符串会默认变成科学计数法,如何去除?

将科学记数法格式的字符串字符转换为标准记数法

在 Gnuplot 中关闭科学记数法