Epsilon
Epsilon 是可以与 1.0 相加并产生与 1.0 不同的结果的最小值。正如 Poita_ 所暗示的,这对于处理舍入误差很有用。情况非常简单:普通浮点数的精度保持固定,无论数字的大小如何。稍微不同地说,它总是计算出相同数量的有效数字。例如,一个典型的实现double
将有大约 15 位有效数字(即 Epsilon = ~1e-15)。如果您使用 10e-200 范围内的数字,则它可以表示的最小变化约为 10e-215。如果您使用 10e+200 范围内的数字,则它可以表示的最小变化约为 1e+185。
有意义地使用 Epsilon 通常需要将其缩放到您正在使用的数字范围,并使用它来定义您愿意接受的范围(可能是由于舍入误差),因此如果两个数字落在该范围内,您假设他们可能真的平等。例如,对于 1e-15 的 Epsilon,您可能决定将彼此在 1e-14 范围内的数字视为相等(即,有效数字已因舍入而丢失)。
可以表示的最小数字通常会比该数字小得多。具有相同的典型double
,通常约为 1e-308。这相当于 Epsilonif您使用的是定点数而不是浮点数。例如,曾经有不少人对各种图形使用定点。典型的版本是将 16 位整数分解为小数点前 10 位和小数点后 6 位。这样的数字可以表示大约从 0 到 1024 的数字,小数点后大约有两位(十进制)数字。或者,您可以将其视为有符号,从(大约)-512 到 +512,同样在小数点后保留大约两位数字。
在这种情况下,缩放因子是固定的,因此两个数字之间可以表示的最小差异也是固定的 - 即 1024 和下一个更大的数字之间的差异与 0 和下一个更大的数字之间的差异完全相同。
倒数
我不确定您到底为什么关心计算极大或极小数字的倒数。 IEEE 浮点使用非正规数,这意味着接近范围限制的数字会失去精度。基本上,数字分为指数和尾数。指数包含数字的大小,有效数包含有效数字。每个都用指定的位数表示。在通常情况下,数字是标准化的,这意味着它们与我们在学校学到的科学记数法有些相似。在科学记数法中,您始终会调整有效数和指数,以便小数点前恰好有一位,因此(例如)140 变为 1.4e2,20030 变为 2.003e4,依此类推。
将其视为浮点数的“标准化”形式。但是,假设您的指数仅限于 2 位数字,因此它只能在 -99 到 +99 之间运行。还假设您最多可以有 15 位有效数字。在这些限制内,您可以生成类似 0.00001002e-99 的数字。这可以让您表示小于 1e-99 的数字,但代价是损失一些精度 - 您使用了 5 位有效数来表示大小,而不是 15 位精度,因此只剩下 10 位数字这确实很重要。
除了它是二进制而不是十进制之外,IEEE 浮点的工作原理大致如此。
当您接近范围的末尾时,数字的精度越来越低,直到(在范围的最末端)只剩下一位精度。
如果你取那个只有一位精度的数字,并取它的倒数,你会得到一个非常大的数字 - 但由于你只从一位精度开始,所以结果也只能有一位精度。虽然比没有结果稍好一些,但仍然接近于毫无意义。您已达到位数所能表示的极限;解决这个问题的唯一方法就是使用更多的比特。
倒数(或其他计算)实际上没有任何一个点“不再有意义”。这并不是一个严格的界限,即一个结果有意义,而另一个结果则没有意义。相反,它是一个斜率,其中一个结果可能具有 15 位精度,另一个结果为 10 位,第三个结果只有 1 位。“有意义”与否主要取决于您如何解释该结果。为了获得有意义的结果,您需要清楚地了解最终结果中有多少位数字是真正有意义的。