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

9

我有一个类似这样的字符串:

"0.4794255386042030002732879352156"

这大约等于sin(0.5)。我想要格式化字符串,使其更美观。

"4.794255386042e-1"

我该如何实现这个?请记住,我处理的是字符串而不是数字(float、double)。另外,我需要四舍五入以保持尽可能准确的数字,不能简单地截断。如果我需要转换为不同的数据类型,我更喜欢使用long double,因为普通的double精度不够。我希望在四舍五入之前至少有12位小数。也许我可以做一个简单的sprintf()转换。

9个回答

9

类似这样的:

#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

6
你是否需要像这样的东西?
以下是一个示例:
 // 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;
}

Output:

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

3

从你的问题中看,似乎你在使用十进制对数。如果是这样,直接扫描字符串,计算前导或尾随零并将其放入指数中,应该相对容易。

也许我漏掉了什么重要信息。


同意。在这种情况下,他可以简单地找到点的位置,移动它,并将指数附加为点移动的方向和距离的计数。 - Clifford

2

使用sscanf()将其转换为长双精度,然后使用科学计数法格式的sprintf()将其打印回字符串中:

long double x;
char num[64];

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

不确定即使使用long double是否实际提供12个有效数字。在我的系统上,这将生成"4.79425538604e-01"


你的意思是如果(sscanf(string, "%Lf", &x) == 1)吗?因为%Ld会给出一个长整数。 - John Scipione

2

IEEE 754标准的64位浮点数(即双精度),可以表示15个有效数字,因此将其转换为double类型应该没有问题。但更可能遇到的问题是如何使格式说明符显示所有可用数字。尽管从已发布的示例中看来,这似乎不是问题。


你是对的,一个double足够好了,一旦我添加了适当的格式字符串,我甚至可以从一个double中得到17个小数位,我相信我可以得到更多,但那已经足够了。 - John Scipione
你不可能用double类型实现这个,事实上即使你认为你可以,17也是不可能的。尾数有52位,2^52是一个16位数字,因此限制是15位数字(数学上是15.65位),因为52位足以表示所有可能的15位数字。请注意,我谈论的是有效数字而不是小数位数。 - Clifford

0
#include <iostream>
using namespace std;
...
double dd = strtod( str );
cout << scientific << dd << endl;

不,那输出的是0.4794255386042030002732879352156,这不是他要求的。 - dcp
不,它输出的是4.794255e-01(默认精度为6)。 “cout.precision(12)”将把它设置为十二。 - Sanjaya R

0
根据您想要的小数位数(在此情况下为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终止。


0

在C或C++中没有标准函数可以完成这个任务。通常的方法是将其转换为数字(然后使用标准函数格式化数字)或编写自己的自定义输出函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接