鱼C论坛

 找回密码
 立即注册
查看: 2176|回复: 7

初学者求e近似值为什么只输出了短短几位

[复制链接]
发表于 2019-11-3 09:25:19 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能^_^

您需要 登录 才可以下载或查看,没有账号?立即注册

x
/*7.计算自然底数e的近似值:
公式 e=1+1/1!+1/2!+...+1/n! 直到最后一项值小于10^-8时运算结束
*/
#include<iostream>
using namespace std;
int main()
{
        int n;
        double p=1.0,pn,a=1.0;
        for(n=1;;n=n+1)
        {
                p=n*p;
                pn=1/p;
                a=a+pn;
                if(pn<1e-8)
                {
                        break;
            }
        }
       
        cout<<a;
       
       
       
}
//输出结果为:2.71828

想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复

使用道具 举报

发表于 2019-11-3 10:53:52 | 显示全部楼层
      用 Python 编写代码可以不用考虑在 C 语言中由于 double 型变量字节数局限而带来的精度问题:
p , e , n = 1.0 , 1.0 , 1
while p < 1e8:
    p *= n
    e += 1 / p
    n += 1
print(e)
    这个便是 Python 代码算出的结果:
C:\Bin>python x.py
2.71828182829
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

 楼主| 发表于 2019-11-3 11:12:03 | 显示全部楼层
jackz007 发表于 2019-11-3 10:53
用 Python 编写代码可以不用考虑在 C 语言中由于 double 型变量字节数局限而带来的精度问题:

    ...

大哥,我这是C++啊
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-11-3 11:21:06 | 显示全部楼层
本帖最后由 jackz007 于 2019-11-3 11:31 编辑

        我知道是 C++,这不,我不是专门把 C++ 代码翻译成 Python 代码了?

        多一个角度看世界难道不好吗?

        Python 可以直接计算任意大小的数值,其位数只受内存大小的限制,不像 C ++,char 是 1 字节,short int 是 2 个字节,int 和 float 是 4 字节,long long 和 double 是 8 字节,表达能力和精度都受到了局限,如果不考虑数值边界,很容易导致计算溢出,常常是得到错误的计算结果而不自知。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-11-3 12:03:20 | 显示全部楼层
本帖最后由 jackz007 于 2019-11-3 12:13 编辑
zhaoenjiang 发表于 2019-11-3 11:12
大哥,我这是C++啊


      例如,计算阶乘,用 C ++ 可以计算的最大阶数用这个代码确定:
#include <stdio.h>

main(void)
{
        unsigned long long d                                          ;
        int k                                                         ;
        for(d = 0xffffffffffffffff , k = 0 ; d > 1 ; d /= (k ++ + 1)) ;
        printf("%u\n" , k - 1)                                        ;
}

      计算结果是 20,意味着如果计算 20 以上的阶乘会导致溢出,其结果一定是错的!

      可是,在同一台电脑上,用 Python 却可以立即计算出 2000 的阶乘,就下面三两句代码足够了:
m = 1
for x in range(2000):
    m *= (x + 1)
print(m) 
      这个就是计算结果:
331627509245063324117539338057632403828111720810578039457193543706038077905600822400273230859732592255402352941225834109258084817415293796131386633526343688905634058556163940605117252571870647856393544045405243957467037674108722970434684158343752431580877533645127487995436859247408032408946561507233250652797655757179671536718689359056112815871601717232657156110004214012420433842573712700175883547796899921283528996665853405579854903657366350133386550401172012152635488038268152152246920995206031564418565480675946497051552288205234899995726450814065536678969532101467622671332026831552205194494461618239275204026529722631502574752048296064750927394165856283531779574482876314596450373991327334177263608852490093506621610144459709412707821313732563831572302019949914958316470942774473870327985549674298608839376326824152478834387469595829257740574539837501585815468136294217949972399813599481016556563876034227312912250384709872909626622461971076605931550201895135583165357871492290916779049702247094611937607785165110684432255905648736266530377384650390788049524600712549402614566072254136302754913671583406097831074945282217490781347709693241556111339828051358600690594619965257310741177081519922564516778571458056602185654760952377463016679422488444485798349801548032620829890965857381751888619376692828279888453584639896594213952984465291092009103710046149449915828588050761867924946385180879874512891408019340074625920057098729578599643650655895612410231018690556060308783629110505601245908998383410799367902052076858669183477906558544700148692656924631933337612428097420067172846361939249698628468719993450393889367270487127172734561700354867477509102955523953547941107421913301356819541091941462766417542161587625262858089801222443890248677182054959415751991701271767571787495861619665931878855141835782092601482071777331735396034304969082070589958701381980813035590160762908388574561288217698136182483576739218303118414719133986892842344000779246691209766731651433494437473235636572048844478331854941693030124531676232745367879322847473824485092283139952509732505979127031047683601481191102229253372697693823670057565612400290576043852852902937606479533458179666123839605262549107186663869354766108455046198102084050635827676526589492393249519685954171672419329530683673495544004586359838161043059449826627530605423580755894108278880427825951089880635410567917950974017780688782869810219010900148352061688883720250310665922068601483649830532782088263536558043605686781284169217133047141176312175895777122637584753123517230990549829210134687304205898014418063875382664169897704237759406280877253702265426530580862379301422675821187143502918637636340300173251818262076039747369595202642632364145446851113427202150458383851010136941313034856221916631623892632765815355011276307825059969158824533457435437863683173730673296589355199694458236873508830278657700879749889992343555566240682834763784685183844973648873952475103224222110561201295829657191368108693825475764118886879346725191246192151144738836269591643672490071653428228152661247800463922544945170363723627940757784542091048305461656190622174286981602973324046520201992813854882681951007282869701070737500927666487502174775372742351508748246720274170031581122805896178122160747437947510950620938556674581252518376682157712807861499255876132352950422346387878954850885764466136290394127665978044202092281337987115900896264878942413210454925003566670632909441579372986743421470507213588932019580723064781498429522595589012754823971773325722910325760929790733299545056388362640474650245080809469116072632087494143973000704111418595530278827357654819182002449697761111346318195282761590964189790958117338627206088910432945244978535147014112442143055486089639578378347325323595763291438925288393986256273242862775563140463830389168421633113445636309571965978466338551492316196335675355138403425804162919837822266909521770153175338730284610841886554138329171951332117895728541662084823682817932512931237521541926970269703299477643823386483008871530373405666383868294088487730721762268849023084934661194260180272613802108005078215741006054848201347859578102770707780655512772540501674332396066253216415004808772403047611929032210154385353138685538486425570790795341176519571188683739880683895792743749683498142923292196309777090143936843655333359307820181312993455024206044563340578606962471961505603394899523321800434359967256623927196435402872055475012079854331970674797313126813523653744085662263206768837585132782896252333284341812977624697079543436003492343159239674763638912115285406657783646213911247447051255226342701239527018127045491648045932248108858674600952306793175967755581011679940005249806303763141344412269037034987355799916009259248075052485541568266281760815446308305406677412630124441864204108373119093130001154470560277773724378067188899770851056727276781247198832857695844217588895160467868204810010047816462358220838532488134270834079868486632162720208823308727819085378845469131556021728873121907393965209260229101477527080930865364979858554010577450279289814603688431821508637246216967872282169347370599286277112447690920902988320166830170273420259765671709863311216349502171264426827119650264054228231759630874475301847194095524263411498469508073390080000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
      即便是计算 20000 的阶乘也不在话下,只是本坛每个帖子有 5000 字的限制,计算结果太长根本无法贴下。
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-11-3 17:09:24 | 显示全部楼层

C语言版本

本帖最后由 bin554385863 于 2019-11-3 21:08 编辑
#include <stdio.h>
double fact(int n)
{
        double fact = 1;
        if (n < 0)
        {
                fact = -1;
                printf("DATE ERROR");
        }
        else if (n == 0)
        {
                fact = 1;
        }
        else
        {
                for (int i = 1; i <= n; i++)
                {
                        fact *= i;
                }
        }
   return fact;
}
int main(int argc, char * argv[])
{
        double _e = 1;
           int a = 0;
           for(int i = 1; 1/fact(i) > 1e-8; i++)
           {
                _e += 1/fact(i);
                  a = i;
           }
           printf("%d---->%20.19f", a, _e);
        return 0;
}
2345截图20191103170849.png
%20.19f表示输出20位有效数字且保留19位小数
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-11-3 17:30:57 | 显示全部楼层

C++版本

本帖最后由 bin554385863 于 2019-11-3 21:12 编辑
#include <iostream>
#include <iomanip>
double fact(int n)
{
    double fact = 1;
    if (n < 0)
    {
        fact = -1;
        std::cout << "DATE ERROR" << std::endl;
    }
    else if (n == 0)
    {
        fact = 1;
    }
    else
    {
        for (size_t i = 1; i <= n; i++)
        {
            fact *= i;
        }
    }
    return fact;
}
int main(int argc, char const *argv[])
{
    double _e = 1;
    for (size_t i = 1; fact(i) < 1e+8; i++)
    {
        _e += 1/fact(i);
    }
    std::cout<<std::fixed<<std::setprecision(19)<<_e;
    return 0;
}
std::fixed  表示不用科学计数输出数据(C++默认很长的数字用科学计数法输出)
std::setprecision(n)  表示保留n位小数
C++的输出格式化设置全在头文件<iomanip>中

-----------------------------------------------------
Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

尝试新的跨平台 PowerShell https://aka.ms/pscore6

PS E:\Users\admin\Documents\VScode> & 'c:\Users\admin\.vscode\extensions\ms-vscode.cpptools-0.26.1\debugAdapters\bin\WindowsDebugLauncher.exe' '--stdin=Microsoft-MIEngine-In-lzfhqchb.312' '--stdout=Microsoft-MIEngine-Out-300jw5sz.i5b' '--stderr=Microsoft-MIEngine-Error-jhq3kdsr.fm2' '--pid=Microsoft-MIEngine-Pid-exp2ai2c.otj' '--dbgExe=D:\MinGW\bin\gdb.exe' '--interpreter=mi'
2.7182818261984929009
PS E:\Users\admin\Documents\VScode>
默认情况下double保留6位有效数字
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

发表于 2019-11-4 11:54:08 | 显示全部楼层
本帖最后由 jackz007 于 2019-11-4 12:05 编辑
zhaoenjiang 发表于 2019-11-3 11:12
大哥,我这是C++啊


      你的代码只能保证 e 的小数点后 8 位都是正确的,如果要保证更高的精度,循环次数就得继续增加。

      下面的代码可以保证 e 小数点后15位都是正确有效的:
#include <stdio.h>

int main(void)
{
        double d , e                                                              ;
        unsigned long long k                                                      ;
        for(d = 1.0 , e = 1.0 , k = 1 ; d < 1e16 ; d *= k , e += 1.0 / d  , k ++) ;
        printf("%.16lf\n" , e)                                                    ;
}
C:\Bin>g++ -o ex ex.c

C:\Bin>ex
2.7182818284590455

C:\Bin>

2.7182818284590455

      红字部分的精度是有保证的
想知道小甲鱼最近在做啥?请访问 -> ilovefishc.com
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|鱼C工作室 ( 粤ICP备18085999号-1 | 粤公网安备 44051102000585号)

GMT+8, 2024-10-4 19:24

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表