计算器开发遇到精度问题,请指导我

深_SHEN 2013-01-25 10:58:27
很简单的问题,
tan(arcsin(sqrt(2.0)/2.0))-1.0
很显然,2分之根2求arcsin就是45度,求tan自然是1.0

但对计算机,就不那么简单了。
计算机得到的tan的结果是1.0000000000000002
1和0总数是16位。

但减1后,结果是2.2...×10^-16显然不是0。
我不敢冒然去掉不可靠的位,因为怕影响后续计算。

据我分析,这是因为减1后,计算机把不可靠的0后的2,当作了有效数字。所以导致了上述结果。
那我怎么办才好呢。
...全文
977 37 打赏 收藏 转发到动态 举报
写回复
用AI写文章
37 条回复
切换为时间正序
请发表友善的回复…
发表回复
lm_whales 2013-04-28
  • 打赏
  • 举报
回复
引用 35 楼 sz3602 的回复:
[quote=引用 33 楼 lm_whales 的回复:] 如果计算不够精确,就开高精度计算吧;如果足够了,就用内部类型计算! 这个没有必要纠结。看实际应用的需要就可以了!
引用 34 楼 lm_whales 的回复:
比如Windows XP提供的计算器,应该是高精度计算,浮点数计算精度是不够的。 可以自定义128 位,256位整数,浮点数然后计算精度就自然够了!
和精度无关,我只想显示的时候能正确显示即可[/quote] 这个恰恰和精度有关系,如果表示不精确很多时候,是不可能显示精确的。 而什么时候表示精确和浮点数结构有关系,有些可以精确表示,显示没有问题。 有些虽然表示不十分精确,也可以正确显示。 但是要想所有数都正确显示,有点困难。 另外浮点数要正确显示必须必须在表示极限以内。 比如 15 为 精度表示极限,那就用13位,12位,可以大致精确显示出来但是不能保证,一定不会出现不精确的情况。 如果用高精度计算,还是可以以任意精度,精确表示的。
深_SHEN 2013-04-12
  • 打赏
  • 举报
回复
引用 33 楼 lm_whales 的回复:
如果计算不够精确,就开高精度计算吧;如果足够了,就用内部类型计算! 这个没有必要纠结。看实际应用的需要就可以了!
引用 34 楼 lm_whales 的回复:
比如Windows XP提供的计算器,应该是高精度计算,浮点数计算精度是不够的。 可以自定义128 位,256位整数,浮点数然后计算精度就自然够了!
和精度无关,我只想显示的时候能正确显示即可
haierpro 2013-04-12
  • 打赏
  • 举报
回复
其实现实中也就只有2楼的做法,让显示结果的精度比计算精度低就行了。 至于怎么降低显示精度,了解一下float类型的内存格式,有效数部分取出来做取舍,指数部分不动就可以了。 比如1.0000000000000002,这里有效位有17位,可以只取10位(位数也随便定,只要比16小就行了),四舍五入法和舍去法都可以。 再比如1.23456x10^-50,这里有效数字是1.23456,总长度才6位,完全在输出精度范围内,不用就不用做近似了。
lm_whales 2013-04-07
  • 打赏
  • 举报
回复
比如Windows XP提供的计算器,应该是高精度计算,浮点数计算精度是不够的。 可以自定义128 位,256位整数,浮点数然后计算精度就自然够了!
lm_whales 2013-04-07
  • 打赏
  • 举报
回复
如果计算不够精确,就开高精度计算吧;如果足够了,就用内部类型计算! 这个没有必要纠结。看实际应用的需要就可以了!
深_SHEN 2013-03-30
  • 打赏
  • 举报
回复
问题仍未解决, double d; d= 5.2 * pow(10.0, -50) * tan(asin(sqrt(2.0)/2.0)); if (d<DBL_EPSILON) printf("zero!\n"); else printf("non-zero!\n"); 结果不幸,是zero,应该是non-zero,要注意到5.2e-50是一个用户输入的数字,并且在数学上5.2是有效的数字,但是此处被程序误认为0,很不幸; double d; d= tan(asin(sqrt(2.0)/2.0)) - 1.0; if (d<DBL_EPSILON) printf("zero!\n"); else printf("non-zero!\n"); 结果不幸,是non-zero,但理论上d应该严格是0,会导致显示问题很不幸; double d; d= tan(asin(sqrt(2.0)/2.0)) - 1.0; if (d<=DBL_EPSILON) printf("zero!\n"); else printf("non-zero!\n"); 预料之内是zero,因为从调试器中看到,d==DBL_EPSILON是真; 故在第一种情况下,只用<DBL_EPSILON是万万不行的。 所以通过大家讨论,还是无法看出计算结果是否为0。
赵4老师 2013-03-28
  • 打赏
  • 举报
回复
对学习编程者的忠告: 眼过千遍不如手过一遍! 书看千行不如手敲一行! 手敲千行不如单步一行! 单步源代码千行不如单步对应汇编一行! VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。 对VC来说,所谓‘调试时’就是编译连接通过以后,按F10或F11键单步执行一步以后的时候,或者在某行按F9设了断点后按F5执行停在该断点处的时候。
mujiok2003 2013-03-28
  • 打赏
  • 举报
回复
1. 函数Sin等已经引入了误差,除非你自己实现,否则你要得到精确值是办不到的。 2. 浮点数可以直接和0比较,没有问题。 double a; a = 0; 0 == a;//true a = 1e-19; 0 == a;//false
baichi4141 2013-03-28
  • 打赏
  • 举报
回复
顺便说一下,windows自带的计算器没有楼主想要的这个美化功能,tan(45)-1显示出来的结果不是0 大概是因为在微软看来,精确比美观更重要吧
baichi4141 2013-03-28
  • 打赏
  • 举报
回复
1.000000000000000和1.0000000000000002,计算机分不出来这两个数之间有什么区别。当然,人肉眼可以判断,前者后面一串0,后者一串0后面跟个2,不自然,但自然不自然跟对不对没关系 3.12354234254242432和3.12354234254242433,哪个更自然?哪个更正确?你看数值本身看不出来。要精确,就只能算出多少是多少,你任何“让这个数值看起来更自然”的行为,都是在增大误差 根据浮点数的表示方式,用浮点数来表示1.46823×10-50这个数不可能是精确的,如果楼主以为这个数是精确地,那只能说楼主根本就没弄懂浮点数是什么东西 你看这个数的十进制表示后面部分全是0,计算机里用于存储它的二进制可不是一堆0,所以1.46823×10-50跟1.468230000001×10-50,计算机根本不可能区分它们 要像人肉眼一样区分,那只能把两个数都按十进制打印成字符串,然后看哪边一堆0——这是为了美观而进行的字符串处理,而不是数学上的精确计算 楼主想要的功能,只能通过字符串处理实现 先在内存中打印成字符串,然后遍历每一个字符,看哪个字符串后面一堆0,就选择这个字符串去掉0后显示出来
yhuib 2013-03-28
  • 打赏
  • 举报
回复
你得确定你的系统有效位数是多少位,每步都只处理和显示相应的位数,超过部分四舍五入
深_SHEN 2013-03-25
  • 打赏
  • 举报
回复
引用 25 楼 zhao4zhong1 的回复:
引用 24 楼 sz3602 的回复:引用 23 楼 zhao4zhong1 的回复:结合16楼理解15楼,还是理解不了,请在百度搜“浮点表示法”。 您好,我看了浮点表示法,但是感觉和我的问题没有关系,可能我还没有理解您的意思。 我知道不能用浮点数精确表示一个数字,我想要的就只是计算出tan(arcsin(sqrt(2.0)/2.0))-1.0=0.0即可。 有办法……
感谢您的回答,但是有这样一个问题: Ans = tan(arcsin(sqrt(2.0)/2.0))*5.3*10^-20这个数的结果是Ans = 5.3*10^-20而非零,所以用 if (fabs(Ans)<DBL_EPSILON) 判断是不行的。
深_SHEN 2013-03-01
  • 打赏
  • 举报
回复
引用 23 楼 zhao4zhong1 的回复:
结合16楼理解15楼,还是理解不了,请在百度搜“浮点表示法”。
您好,我看了浮点表示法,但是感觉和我的问题没有关系,可能我还没有理解您的意思。 我知道不能用浮点数精确表示一个数字,我想要的就只是计算出tan(arcsin(sqrt(2.0)/2.0))-1.0=0.0即可。 有办法吗? 判断结果是否小于DBL_EPSILON而人为置0.0是不行的。因为例如1.23456x10^-50虽然小于DBL_EPSILON,但它不等于0.0
赵4老师 2013-03-01
  • 打赏
  • 举报
回复
引用 24 楼 sz3602 的回复:
引用 23 楼 zhao4zhong1 的回复:结合16楼理解15楼,还是理解不了,请在百度搜“浮点表示法”。 您好,我看了浮点表示法,但是感觉和我的问题没有关系,可能我还没有理解您的意思。 我知道不能用浮点数精确表示一个数字,我想要的就只是计算出tan(arcsin(sqrt(2.0)/2.0))-1.0=0.0即可。 有办法吗? 判断结果是否小于DBL_E……
#include <stdio.h>
#include <math.h>
#include <float.h>
int main() {
    double d;

    d=tan(asin(sqrt(2.0)/2.0))-1.0;
    printf("tan(arcsin(sqrt(2.0)/2.0))-1.0=%3.1lf\n",d);
    if (fabs(d)<DBL_EPSILON) {
        printf("OK.\n");
    } else {
        printf("Error!\n");
    }
    return 0;
}
//tan(arcsin(sqrt(2.0)/2.0))-1.0=0.0
//OK.
赵4老师 2013-02-04
  • 打赏
  • 举报
回复
结合16楼理解15楼,还是理解不了,请在百度搜“浮点表示法”。
深_SHEN 2013-02-03
  • 打赏
  • 举报
回复
引用 15 楼 zhao4zhong1 的回复:
include\float.h C/C++ code?12345678910111213...#define DBL_DIG 15 /* # of decimal digits of precision */#define DBL_EPSILON 2.2204460492503131e-016 /* sm……
我还是没懂。能再说清楚一点吗
深_SHEN 2013-01-31
  • 打赏
  • 举报
回复
没有办法吗??
赵4老师 2013-01-29
  • 打赏
  • 举报
回复
15楼正解!
深_SHEN 2013-01-29
  • 打赏
  • 举报
回复
其实有误差不怕,我就是想显示的时候不显示误差。 减法能改变有效数字个数,例如本帖的例子。由于有效数位改变了,所以出现了错误。 我不在意计算是否有误差。
深_SHEN 2013-01-29
  • 打赏
  • 举报
回复
引用 19 楼 zhao4zhong1 的回复:
15楼正解!
请问怎么正解了?我都说了,1.23456x10^-50都是准确的。我没明白怎么就正解了?
加载更多回复(17)
特等奖标准成品论文(Word无水印纯净版) 硬核结构:全文包含完整的摘要、问题重述与分析、模型假设、符号说明、模型建立与求解、灵敏度分析及结论。 即插即用:排版严格遵循官方规范,逻辑严密。拿到手即可作为绝佳的高分参考模板,稍作替换与个性化润色即可极速完稿,彻底解决写论文难的痛点。 双源硬核解题代码(Python与MATLAB双版本) 拒绝假代码:提供底层逻辑清晰、模块化设计的全套可运行源码。 全流程覆盖:涵盖从前期数据清洗预处理,到中期核心数学模型训练,再到后期启发式算法寻优。 傻瓜式运行:代码自带详尽的逐行中文注释,并支持一键生成高质量结果可视化图表,编程小白也能轻松复现与二次开发。 全量数据与结果展示表 所有中间处理数据、模型输出参数以及最终结论,均已精细整理成高质量表格。直观呈现性能评估指标与多模型对比分析,可直接作为论文正文或附件使用,极大提升学术说服力。 独家硬核思路解析 深入浅出剖析出题人意图,详细拆解每一小问的数学本质与底层逻辑,让你不仅知其然更知其所以然。 【四大核心产品优势】 高效实用:所有代码与论文均经过严格测试,确保结果精准无误、完全可复现,省去熬夜试错的时间。 全栈覆盖:从思路分析到跑出结果,再到写出高质量论文,提供一站式全流程资料矩阵。 排版辅助:资料内提供专业的论文排版一键转换工具与官方标准模板,告别格式调整的繁琐。 持续迭代:网盘直发,开赛后资料库将持续滚动更新,所有用户均可免费同步获取最新包。 【适用人群】 想要打破建模瓶颈的参赛队长与主攻手;急需高质量底层代码的编程小白;目标直指特等奖需要高分模板对标的精英团队。
内容概要:本文围绕分布式光伏储能系统的优化配置方法展开,重点基于Matlab代码实现系统建模与仿真分析,涵盖光伏出力不确定性、负荷响应特性及储能充放电行为的综合建模。通过引入改进鲸鱼优化算法、粒子群算法等智能优化算法,解决系统容量配置、能量管理策略与多目标优化调度等问题,旨在提升系统运行效率、降低能耗成本并延长设备使用寿命。研究内容还包括并网与离网模式下的经济性对比、微电网能量优化管理、储能配置方案评估,并提供完整的Matlab代码、数据集及论文撰写模板,支持科研成果的高效产出。; 适合人群:具备电力系统、新能源技术或自动化等相关专业背景,熟悉Matlab/Simulink仿真环境的研究生、科研人员及工程技术人员;特别适用于计划撰写EI/SCI期刊论文的高层次研究人员。; 使用场景及目标:①开展分布式光伏储能系统配置的科研课题与学术论文撰写;②实现微电网能量管理系统的设计与优化调度算法验证;③掌握基于Matlab的多目标优化建模方法,提升在新能源系统规划与运行领域的科研创新能力。; 阅读建议:建议结合提供的Matlab代码与Simulink模型进行动手实践,重点关注优化算法的实现逻辑与参数调优过程,按照文档目录循序渐进学习,构建完整的知识体系,并参考配套论文模板完成研究成果的规范化输出。
监控系统粘贴板和时间截的小软件(开源成世) 梅菉佬--惊屎无人知 2026-06-05 ①使用电脑,经常要用到剪贴板历史的,在windows10中有系统的,但是在ubuntu24中,我找不到,找第三方软件,也是各种不顺限制,有的版本变了就无法使用,又或这样那样的要求,不如干脆自已做一个自用吧。 ②先是,读出粘贴板的历史数据,主要是文本,至于非文本格式,暂不理吧,手机粘贴板历史也是如是。 ③发现,还要加上当前时间截,这个功能很小,但很实用,很多系统没有自带这功能,自已在ubuntu24中加上lazarus用托盘小软件,轻松实现。 ④发现,最好加上常用的难打字,如,塘㙍的㙍字,这个字平时不容易打字出来,事先放入小软件中,到时当成粘贴板历史数据取出来用就行了。又发现,一些五笔中能记忆的字,也可如是,例如,逐,垂,等字。还有一些特殊符号,手机上有,电脑难找但要以显示的,例如,☆★①②③④⑤,还有,一些平时要常查但难记忆的,例如linux的命令,快捷键,也可以加入,相当于托盘记事本。。。。 ⑤还有,在ubuntu中,加入到开机启动中,测试顺利可用。还有,编程时,加入ini文件,可以使用时编写文本,不用每次编译源码。还有,要用分级菜单功能,暂定二级树形菜单,否则太难看了。刚开始用最简单的timer来读取粘贴板数据,后来找到别的API,不用timer了,但是,linux的API比起windows的API,似乎难找得多了。。。 于是,自产自用小工具产生了。实测可用。独乐乐不如众乐乐,于是,开源,念心经,惊S无人知,压惊也,这点小事被卡住,多么不抵。。。 //显式初始化GTK(安全调用)

3,881

社区成员

发帖
与我相关
我的任务
社区描述
C/C++ 其它技术问题
社区管理员
  • 其它技术问题社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧