Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sql-server-2005/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 为什么像1.82这样的简单双打最终会变成1.81999999645634565360?_C++_Double_Precision - Fatal编程技术网

C++ 为什么像1.82这样的简单双打最终会变成1.81999999645634565360?

C++ 为什么像1.82这样的简单双打最终会变成1.81999999645634565360?,c++,double,precision,C++,Double,Precision,可能重复: c++ 嘿,我在做一个函数来返回给定数字数据类型中的数字,但是我在使用double时遇到了一些问题 我通过将它乘以100亿,然后去掉数字1乘以1,直到双精度为0,计算出其中有多少个数字。但是,当输入一个双精度值(比如.7904)时,我永远不会退出该函数,因为它会不断地删除一些数字,这些数字最终不会是0,因为.7904的结果最终是7903999888,而不是7904000000 我如何解决这个问题??谢谢欢迎对我的代码进行任何其他反馈 以下是我的函数代码: /////////////

可能重复:

c++

嘿,我在做一个函数来返回给定数字数据类型中的数字,但是我在使用double时遇到了一些问题

我通过将它乘以100亿,然后去掉数字1乘以1,直到双精度为0,计算出其中有多少个数字。但是,当输入一个双精度值(比如.7904)时,我永远不会退出该函数,因为它会不断地删除一些数字,这些数字最终不会是0,因为.7904的结果最终是7903999888,而不是7904000000

我如何解决这个问题??谢谢欢迎对我的代码进行任何其他反馈

以下是我的函数代码:

///////////////////////     Numb_Digits()   ////////////////////////////////////////////////////
        enum{DECIMALS = 10, WHOLE_NUMBS = 20, ALL = 30};
    template<typename T>
unsigned long int Numb_Digits(T numb, int scope)
{
        unsigned long int length= 0; 
    switch(scope){
        case DECIMALS:      numb-= (int)numb;   numb*=10000000000; // 10 bil (10 zeros)
            for(; numb != 0; length++)
                numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;

        case WHOLE_NUMBS:   numb= (int)numb;    numb*=10000000000; 
            for(; numb != 0; length++)
                numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;

        case ALL:           numb = numb;        numb*=10000000000;
            for(; numb != 0; length++)
                numb-=((int)(numb/pow((double)10, (double)(9-length))))* pow((double)10, (double)(9-length)); break;

        default: break;}
                                            return length;
};

int main()
{
    double test = 345.6457;
    cout << Numb_Digits(test, ALL) << endl; 
    cout << Numb_Digits(test, DECIMALS) << endl;
    cout << Numb_Digits(test, WHOLE_NUMBS) << endl;

    return 0;
}
/////////Numb\u数字()////////////////////////////////////////////////////
枚举{小数=10,整数=20,全部=30};
模板
无符号长整数Numb_位(T Numb,整数范围)
{
无符号长整型长度=0;
开关(范围){
大小写小数:numb-=(int)numb;numb*=1000000000;//10bil(10个零)
对于(;numb!=0;长度++)
numb-=((int)(numb/pow((双)10,(双)(9长))*pow((双)10,(双)(9长));中断;
整个案例:numb=(int)numb;numb*=1000000000;
对于(;numb!=0;长度++)
numb-=((int)(numb/pow((双)10,(双)(9长))*pow((双)10,(双)(9长));中断;
所有案例:numb=numb;numb*=1000000000;
对于(;numb!=0;长度++)
numb-=((int)(numb/pow((双)10,(双)(9长))*pow((双)10,(双)(9长));中断;
默认值:break;}
返回长度;
};
int main()
{
双重测试=345.6457;
CUT> P>这是因为C++(和大多数其他语言一样)不能存储具有无穷精度的浮点数字。
浮点存储方式如下:
符号*系数*10^指数
如果使用基数10。
问题是
系数
指数
都存储为有限整数

这是在计算机程序中存储浮点的常见问题,通常会出现微小的舍入误差

最常见的处理方法是:

  • 将数字存储为分数(x/y)
  • 使用允许小偏差的增量(如果abs(x-y)<增量)
  • 使用第三方库,如GMP,它可以以完美的精度存储浮点
关于计算小数的问题。
如果您获得双精度输入,则无法处理此问题。您无法确定用户是否实际发送了1.81999999645634565360,而不是1.82

要么你必须改变你的输入,要么改变你函数的工作方式


有关浮点的更多信息可以在这里找到:

您应该始终使用浮点数字检查相对差异,而不是绝对值


你也需要阅读。

计算机不能准确地存储浮点数。要完成你正在做的事情,你可以将原始输入存储为字符串,并计算字符数。

这是因为它们的二进制表示形式,这里将对此进行深入讨论:

基本上,当一个数字不能按原样表示时,使用近似值代替


要比较浮点数是否相等,请检查其差值是否小于任意精度。

这是因为IEEE浮点数标准的实施方式不同,这会因操作而异。这是精度的近似值。从不使用if逻辑(float==float),ever!

有关浮点运算的简单摘要:

读这篇文章,你就会看到光明

如果你更喜欢数学,戈德堡的论文总是很好的:


长话短说:实数以固定的、不规则的精度存储,导致不明显的行为。这与语言无关,但更多的是作为一个整体处理实数的设计选择。

浮点数以有效数字×基本指数的形式表示(IEEE 754).在您的情况下,浮动1.82=1+0.5+0.25+0.0625+


由于只能存储有限的数字,因此,如果浮点数不能表示为相关基数中的终止扩展,则会出现舍入错误(本例中为基数2)

它不是C++,它是直接使用FPUES的任何东西,但是有使用软件计算而不是FPU的编程语言,所以这与你正在使用的语言有关。感谢简单的引用。这是一个很好的介绍。实际上,在浮点计算中收敛的一种测试方法是:代码> A+B==A< /Cord>t。当你知道
b
小到可以忽略时。你的意思是使用ltoa()?我不喜欢这个函数,因为它不是很简单,需要我使用非常量字符数组…你建议如何实现这一点?对不起,我不是C/C++人,所以我不知道具体如何做