如何解决在C中加上两个大双数会导致错误的结果
我想问一个问题,就是要添加两个用C语言加倍的大数字。
让我们说有两个数字加倍:1.31E + 42和1.399E + 43。
如果我在Excel中进行添加,则结果为15300000000000000000000000000000000000000000000000。那应该是正确的。
如果我使用C语言进行加法,则结果为15299999999999999804804719125983728080953278464。
差异很大。在C语言中将双数相加或相乘时,有人知道如何获得正确的结果吗?
我必须添加另一个重要信息。一件事是将其打印出来。我知道可以按照你们的建议打印号码。但是我也需要它作为另一项工作的价值。具体而言,这是分析两个圆的任务-它们的相交和/或接触(如果它们在外部或内部相接触,或者存在相交)。 https://www.bbc.co.uk/bitesize/guides/z9pssbk/revision/4 如果两个圆心之间的距离(V)等于其半径之和(外部接触)或半径之差(内部接触),则两个圆会接触。因此,我必须对外部触摸进行加法运算,然后比较它们的中心V之间的距离是否等于其半径之和。因此,这不仅仅是打印出价值。
第一个圈子:
Sx = -3.2E+41,Sy = -3.31E+42,R = 1.31E+42
第二圈:
Sx = 1.354E+43,Sy = 3.17E+42,R = 1.399E+43
两个C语言中心之间的距离是:
V = 15300000000000002280599204554488630751526912.000000
其半径之和为C语言:
SumR =15299999999999999804719125983728080953278464.000000
根据参考,它们应该在外部进行触摸,因此,如果执行以下条件,我将获得没有外部触摸的信息。
if (fabs(V - SumR) < 0.001)
printf("There is an external touch")
else
printf("No external touch")
解决方法
浮点运算近似于实数运算。在将十进制数转换为二进制浮点数或执行浮点算术时,通常不应期望使用实数算术得到的结果。
此答案假设您的C实现对double
使用IEEE-754 binary64格式,并使用从最近到最近的关系到偶数执行算术,包括从十进制到double
的转换。 / p>
binary64格式具有一个符号,一个53位有效数字(数字的“小数部分”)和一个11位指数。
此格式不能代表1.31•10 42 。它可以表示的最接近的值为1310000000000000060347708657386176332693504。当您的C源文本包含1.31e42
时,编译器会将其转换为1310000000000000060347708657176176693693504。如果我们使用十六进制表示有效位数,则为1.E137CED6DF0D1 16 •2 139 。您可以看到开头的“ 1”和另外13个十六进制数字(每个4位)组成53位。
格式也不能代表1.399•10 43 。它可以表示的最接近值为13989999999999999899113922922237014438982975488。当C源文本包含1.399e43
时,编译器会将其转换为13989999999999999899113922237014438982975488。使用十六进制,这是1.4131D470653E9 16 •2 143
添加这些后,通常的数学结果无法表示。产生的结果是最接近的可表示数字,它是152999999999999999999804719125983728080953278464。使用十六进制,它是1.5F45515DD32F6 16 •2 143 。
这是浮点算术所期望的正确结果。为您的目的获得“正确”结果取决于您要完成的工作。对于许多目的,使用浮点数获得近似结果就足够了,并且人们仅理解该结果是近似值。如果需要精确的结果,则必须使用其他格式和软件。
,如果您需要处理大数,则应使用arbitrary precision arithmetic之类的GMPlib(又称大数字)库。
如果要使用浮点数,请花一些时间来阅读floating point guide和有关IEEE 754的知识。它们不遵循real numbers的直观属性(例如,大多数操作都不具有关联性)。
先阅读Modern C和this C reference网站,然后阅读C11标准草案n1570。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。