算术规则是不是适用于 C 中的加法?
Posted
技术标签:
【中文标题】算术规则是不是适用于 C 中的加法?【英文标题】:Do the rules of arithmetic hold for addition in C?算术规则是否适用于 C 中的加法? 【发布时间】:2014-11-13 16:27:35 【问题描述】:我是 C 的新手,我很难理解这种材料。我真的需要帮助!请有人帮忙。
在算术中,任何两个正整数之和都大于任何一个:
(n+m) > n for n, m > 0
(n+m) > m for n, m > 0
C 有一个加法运算符 +。这个算术规则在 C 中是否成立?
我知道这是假的。但是请有人向我解释为什么会这样,我能理解吗?请提供反例?
提前谢谢你。
【问题讨论】:
【参考方案1】:(我不会为你解决这个问题,但会提供一些指导。)
由于不同的原因,整数和浮点运算都是错误的。
整数容易受到overflow 的影响。 将非常小的浮点数m
添加到非常大的数 n
会返回 n
。阅读What Every Computer Scientist Should Know About Floating-Point Arithmetic。
【讨论】:
WECSSKABFPA 读起来很吓人,对与问题直接相关的部分有什么建议吗? 可以补充一点,编译器可能会假设它适用于有符号整数,也就是说,程序员有责任确保它适用(链接的***文章中似乎没有提到,术语溢出似乎意味着环绕(如在汇编中或在带有无符号整数的 C 中),而不是溢出在 C 标准中的含义)。这是唯一无法通过尝试解决的部分。 @OliverCharlesworth:也许这是内涵:如果这很吓人,你不需要浮点数:P【参考方案2】:它不成立,因为 C 的整数不是真正的整数(在数学中)是“抽象的”无限大小的整数。
在 C 中,整数是离散的和数字的,并且使用固定数量的位来实现。这会导致范围有限,并且当您(尝试)超出范围时会出现问题。通常整数会换行,这是非常“不自然”的。
【讨论】:
+1 很好的答案,但我会使用 range 这个词来代替上面的 precision。浮点数的精度有限;整数是在其范围内具有精确精度的整数。 “实数”?双关语? “离散和数字?”你在说什么?是否存在整数是连续和模拟的编程语言?【参考方案3】:我简短的搜索并没有找到描述这些的好答案,所以我宁愿在这里为初学者很好地回答这个问题。
当然,答案是错误的,但为什么会这样呢?
整数
在 C 或任何提供某种整数类型的编程语言中,这种类型并不意味着它在数学意义上。在数学意义上,非负整数的范围从 0 到无穷大。然而,计算机只有有限的存储空间,因此整数必然被限制在小于无穷大的范围内。
仅此一点就证明a + b > a
和a + b > b
不可能一直为真,因为它可以设置所以a
和b
都小于计算机可以在其存储中表示的最大数字, 但a + b
比那个大。
这里到底发生了什么,取决于。有人提到环绕,但不一定如此。 C 语言首先将整数溢出定义为 undefined 行为,如果代码碰巧踩到它,包括火和烟在内的任何事情都可能发生(当然在现实中不会发生,但严格解释标准是可能的,以及对时空连续体的破坏)。
我不会在这里描述环绕的工作原理,因为它超出了问题本身的范围。
浮点数
这里的情况和整数一样:理解为什么数学在这里不能完全适用的关键是计算机的存储空间有限。
计算机内存中的浮点数表示很像科学记数法:尾数和指数。 两者都有一个固定的有限范围,具体取决于浮点变量的类型。
以 10 为底,您可以这样想,就像您的指数范围从 10 ^ -10
到 10 ^ 10
,并且尾数在小数点后有 4 个小数位,总是标准化的。
考虑到这一点,请检查以下示例添加:
1.2345 * (10 ^ 0) + 1.0237 * (10 ^ 5)
5.2345 * (10 ^ 10) + 6.7891 * (10 ^ 10)
第一个是一个例子,其中结果将等于一个输入数字,而两者都大于零。第二个是结果超出范围的示例。
然而,计算机使用的浮点表示能够表示 infinity,并且有两种:positive infinity 和 negative infinity。因此,虽然第一个示例作为证明通过,但第二个示例没有通过,因为该加法的结果是 正无穷大。
但是考虑到这一点,您可以制作另一个校对示例:
3.1416 * (10 ^ 0) + (+ infinity)
当然结果是正无穷,不管你把它加到什么地方。当然正无穷不大于正无穷,所以再次证明。
【讨论】:
以上是关于算术规则是不是适用于 C 中的加法?的主要内容,如果未能解决你的问题,请参考以下文章
Index的“最左前缀规则”是不是适用于SQL Server?
MISRA C 2012 - 规则 21.1 - 以下划线开头的宏