首页 > 其他分享 >庄子之棰 float 和 double 精度不同导致的误差

庄子之棰 float 和 double 精度不同导致的误差

时间:2024-04-14 15:23:32浏览次数:17  
标签:printf double float hm hg 庄子 小数

结论:计算小数时优先选 double,而不是 float

《庄子·天下》

一尺之棰,日取其半,万世不竭。

一米的棍子,一天砍掉一半,问第 n 天(1~20)时被砍掉的总长度是多少?类似的有小球落地反弹一半的路程,下面的代码求的是小球从 50 米高空落地反弹的路程,结果保留十位小数,代码看起来没啥问题,当输入 20 的时候结果是 149.9998321533,而把 float 都换成 double 后结果则变成了 149.9998569489,两者在第五位小数就开始不同了,是算错了吗?不是的,用 python 算出来的结果(下面第二个代码)是 149.99985694885254,float 和 double 的计算结果又比较相近,是什么导致了这一个问题?

通俗的来说是两者的精度导致的问题,误差一点点的积累下来的。float 单精度,能保留 7 位小数;double 双精度,能保留 15 位小数。也就是说小球反弹的高度不足 0.0000001 时,float 计算就会出问题了。下面第三个代码演示了这个问题

// 从 50 米高空落地反弹的路程
#include <stdio.h>
int main()
{
    float h = 50.0;
    float d = 2.0;
    float sum = 0;
    int n;
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        sum = sum + h;
        h = h / d;  // 注意这里没有直接写 h=h/2
        sum = sum + h;
    }
    printf("%.10f", sum);

    return 0;
}
# 计算 20 次落地的路程
h=50.0
s=0
for _ in range(20):
    s+=h
    h/=2
    s+=h
print(s)    # 149.99985694885254

下面的代码运行结果是:

hg!=hm
3.123457 3.123457
3.123457 3.123457
3.123456789012346 3.123456716537476
#include <stdio.h>
int main()
{
    double hm = 3.1234567890123456;
    float hg = hm;
    if (hg == hm) {
        printf("hg==hm\n");
    } else {
        printf("hg!=hm\n");
    }
    printf("%lf %lf\n", hm, hg); // lf f 都默认输出 6 位小数,四舍五入
    printf("%f %f\n", hm, hg);
    printf("%.15lf %.15lf\n", hm, hg); // 超出精度就开始不对劲了
    return 0;
}

Refer

https://github.com/BackMountainDevil/c_qa

标签:printf,double,float,hm,hg,庄子,小数
From: https://www.cnblogs.com/guilinmifen/p/18134177

相关文章

  • scanf 中给 double 用 %f 时赋值异常, float lf, char s 同理
    结论scanf的变量要匹配对应的格式化字符串。floatf,doublelf,charc编译器提示的错误要消除,不消除不能运行;同时尽量消除警告doublefc语言中,给double类型的变量用scanf%f输入赋值时,会发生逻辑上的错误,请看代码#include<stdio.h>intmain(){doublevalue......
  • CF1681C Double Sort 题解
    一道普及-我写了两个半小时题面。需要注意的是,每次交换需要将a和b两个数组同时交换,因此便可以想到唯一可行情况:a,b序列数字间的大小关系必须一致。举个例子2462131317970612在上面的例子中,两个序列中任意\(i\)和\(j\)满足\(a_i\lea_j\)时\(b_i......
  • CF1162B Double Matrix 题解
    传送门说句实话,如果不是先写了Showstopper这道题的话,我应该会在这里卡很久,因为做Showstopper我就卡了很久QwQ。思路太像了,实在是太像了,与Showstopper想比,仅仅就是换成二维数组,求最大值变为找递增矩阵,处理方法一模一样:将数组\(a\)和\(b\)中较小的值存在一个数组里,较......
  • Double dispatch和Visitor
    DoubledispatchandvisitorDispatch运行时多态,通过基类指针查找具体派生类的方法。Singledispatch单派发示例:Base*p=newDerived();p->Func();Doubledispatch派发、分发、分派,可以类比:总机-分机两次dispatch经常发生在使用vector保存同一类层级的指针......
  • Wpf Beginstoryboard Storyboard DoubleAnimation Storyboart.TargetName,Storyboary.
    <Windowx:Class="WpfApp32.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.......
  • WPF Storyboary DoubleAnimationUsingPath PathGeometry
    <Windowx:Class="WpfApp30.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://schemas.microsoft.......
  • 电脑技巧:推荐一款非常好用的文件重复清理工具DoubleKiller
    目录一、软件介绍二、功能介绍三、使用说明四、软件总结一、软件介绍DoubleKiller是一款专为用户解决重复文件问题而精心打造的小巧实用工具,安装包仅为1.2M。对于长期依赖电脑的工作者和电脑的职场人员来说,随着电脑使用时间的增长,电脑中难免会出现大量重复文件,这些......
  • WPF中动画教程(DoubleAnimation的基本使用)
    实现效果今天以一个交互式小球的例子跟大家分享一下wpf动画中DoubleAnimation的基本使用。该小球会移动到我们鼠标左键或右键点击的地方。该示例的实现效果如下所示:页面设计xaml如下所示:<Windowx:Class="AnimationDemo.MainWindow"xmlns="http://schemas.microsof......
  • codeforces div4 Double Strings
    #include<iostream>#include<algorithm>#include<cstring>#include<map>usingnamespacestd;intT,n;strings[900005];map<string,int>mm;//存放每一个字符串是否出现过intmain(){ cin>>T; while(T--){ mm.clear();//每次清空mm里面的数......
  • 第16期 Double Commander 开源免费的Total Commander替代型【体验100款文件管理工具】
     体验背景:我们正在做一款文件版本管理软件,追光几何(追光几何),期待以最无感的方式,解决新一代工程师文件管理的问题,让大家有更多时间去做快乐和有成就感的事情。所以打算体验100款文件管理软件,来取长补短。真实1h体验DoubleCommander是一款开源的跨平台文件管理软件,灵感来源......