下面的代码有什么问题?它在不使用sprintf或ostream的情况下将double转换为string

What is wrong with the following code? It converts double to string without using sprintf or ostream

本文关键字:情况下 ostream sprintf double string 转换 什么 代码 问题      更新时间:2023-10-16

我编写了下面的代码将double转换为string。我不应该使用sprint或ostream。输出很不稳定。

对应输出的输入列表:

    2.0 - 2.0
  • 2.5 - 2.5
  • -2.0 - -2.0
  • 2.987 2.9879947598364142621957397469375
  • -2.987 - -2.9879947598364142621957397469375
这些多余的数字是从哪里来的?如何解决这个问题?下面是我的代码
#include <iostream>
#include <math.h>
using namespace std;
string reverse(string input);
string myDtoA(double num);
string itoa(int num);
int main()
{
    double inp=-2.987;
    cout<<myDtoA(inp)<<endl;
}
string myDtoA(double num)
{
    if(num>0)
    {
        int inPart;
        double intPart,fractPart;
        fractPart = modf(num,&intPart);
        inPart=(int)intPart;
        string ret;
        ret = itoa(inPart);
        if(fractPart!=0)
        {
            ret.append(".");
            double ceilOfFraction = ceil(fractPart);
            while(ceilOfFraction !=0)
            {
                double inP,fP;
                fractPart*=10;
                fP=modf(fractPart,&inP);
                int a =(int)inP;
                ret.append(itoa(a));
                fractPart=fP;
                ceilOfFraction = ceil(fractPart);
            }
        }
        else
        {ret.append(".0");}
        return ret;
    }
    else if(num==0)
    {
        return "0";
    }
    else if(num<0)
    {
        string ret = "-";
        ret.append(myDtoA(-num));
        return ret;
    }
}
string itoa(int num)
{
    char* str = new char[120];
    int i=0;
    // Process individual digits
    while (num != 0)
    {
        int rem = num % 10;
        str[i++] = (rem > 9)? (rem-10) + 'a' : rem + '0';
        num = num/10;
    }
    string ret(str);
    return reverse(ret);
}
/* A utility function to reverse a string  */
string reverse(string input)
{
    return std::string(input.rbegin(), input.rend());
}

浮点输出很难舍入。

这是我找到的关于这个主题的最新论文:

http://www.cs.tufts.edu/~ nr/cs257/归档/florian-loitsch/printf.pdf

在脚注中,你会发现一个参考:

[Steele Jr. and White(2004)] G. L. Steele Jr., J. L. White。如何准确地打印浮点数(回顾性)。20年来ACM SIGPLAN编程语言设计会议《实现1979-1999》,选集,第372-374页。ACM, 2004年。国际标准图书编号1-58113-623-4。doi: 10.1145/989393.989431 .

是一个精彩的阐述。没有人能够从你的程序中挑选出来,告诉你该怎么做。

问题在于您的itoa的实现。如果itoa的输入为0会发生什么?

输入为-2.987,输出-2.9879947598364142621957397469375应该是-2.9870000000000000994759830064140260219573974609375。注意,我的结果中没有零。那些缺失的零是由于itoa中的错误。

一旦您达到处理单个十进制数字的地步,您的itoa就完全是多余的。最好使用一个数组,将整数0到9映射到字符'0'到'9'。(或者你可以利用"0"到"9"在你的电脑上几乎肯定是连续字符的事实。情况并非总是如此,但我可以保证你不会和这样的野兽一起工作。

更好的是认识到以99475983…开头的子字符串是完全无关的。最好将其打印为-2.9870000000000001,甚至更好地打印为-2.987。