按升序遍历所有可表示的小数



如果我取一个float的低31位(指数和尾数(并逐个循环,则生成的浮点数按升序排列,从0开始,到float.MaxValue,然后到float.PositiveInfinity,然后进一步到float.NaN的许多不同位模式。

这个不错的属性似乎不适用于decimal数据类型。有没有办法以类似的方式按升序遍历所有可表示的十进制值(下限和上限之间(?

奖励:有没有快速计算可能的数字的方法?

其他信息:可以将 1.0 和 1.00 计为两个不同的数字。

decimal格式有一个符号位s、一个 96 位有效数f和一个从 0 到 28 的指数e(包括 0 和 28(。(s, f,e( 的表示值为 (−1(sf/10e

将 (s, f,e( 的规范表示定义为 (s, f • 10ne+n( 的最大整数 n,其中f• 10n<296e≤ 28。如果e不是 28,则典型有效数在天花板 (296/10(, 2 96−1 中,包括 296−1。

我们可以通过以下方式按升序循环访问非负decimal值:

设置 s = 0, e = 28。 对于 0 到 2^96 - 1 的 f,包括: 进程 (s, f, e( 作为十进制值。 对于从 27 到 0 的 e,包括: 对于从天花板(2^96/10(到2^96 - 1(含(的f: 进程 (s, f, e( 作为十进制值。

我们可以看到这是升序,因为f上的每个循环都以比前一个循环结尾的更大的表示值开头。我们可以看到每个可表示的值都包括在内,因为任何规范表示(sfe(的值都出现在f的循环中,其中e的值为e。我们可以看到没有重复的值,因为每个可表示的值在其规范表示中只处理一次。

为了将其限制为特定的下限上限 L 和 U,我们可以找到LU的规范表示。这些表示的组成部分告诉我们在哪里开始和结束fe.该算法的另一种形式可能更适合于此。设fLeLL的规范表示的ef,对于fUeU也是如此。那么一个算法是:

(0( 将 s 设置为 0,将 f 设置为 fL,将 e 设置为 eL。 (1( 如果 e ≤ eU 和 f> fU,则停止。 (2( 过程 (s, f, e( 作为十进制数。 (3( 将 f 设置为 f+1。 (4( 如果 f 小于 2^96,请转到 (1(。 (5( 将 e 设置为 e-1,将 f 设置为 f/10。 (6( 转到 (1(。

负数的扩展是显而易见的。

最新更新