如果我取一个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(s•f/10e。
将 (s, f,e( 的规范表示定义为 (s, f • 10n,e+n( 的最大整数 n,其中f• 10n<296和e≤ 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
上的每个循环都以比前一个循环结尾的更大的表示值开头。我们可以看到每个可表示的值都包括在内,因为任何规范表示(s、f、e(的值都出现在f
的循环中,其中e
的值为e。我们可以看到没有重复的值,因为每个可表示的值在其规范表示中只处理一次。
为了将其限制为特定的下限和上限 L 和 U,我们可以找到L和U的规范表示。这些表示的组成部分告诉我们在哪里开始和结束f
和e
.该算法的另一种形式可能更适合于此。设fL
和eL
是L的规范表示的e和f,对于fU
和eU
也是如此。那么一个算法是:
(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(。
负数的扩展是显而易见的。