如果我使用float
的低31位(指数和尾数)并逐一循环,则所得的浮点数将从0
开始到{{1 }},然后到float.MaxValue
,然后再转到float.PositiveInfinity
的许多不同位模式。
这个不错的属性似乎不适用于float.NaN
数据类型。有没有办法以类似的方式以升序循环遍历所有可表示的十进制值(在上下限之间)?
奖金:是否可以快速计算可能的数字?
其他信息:可以将1.0和1.00视为两个不同的数字。
答案 0 :(得分:1)
decimal
格式的符号位 s ,96位有效位 f 和指数 e 从0开始至28(含)。 ( s , f , e )的表示值为(-1) s • f / 10 e 。
定义( s , f , e )的规范表示为( s , f •10 n , e + n )表示最大整数 n ,其中 f •10 n <2 96 和 e ≤28。如果 e 不为28,则规范有效位数在上限(2 96 / 10),2 96 −1(含)范围内。
我们可以通过以下方式按升序遍历非负decimal
值:
Set s = 0, e = 28. For f from 0 to 2^96 - 1, inclusive: Process (s, f, e) as a decimal value. For e from 27 down to 0, inclusive: For f from ceiling(2^96 / 10) to 2^96 - 1, inclusive: Process (s, f, e) as a decimal value.
我们可以看到这是升序的,因为f
上的每个循环都以比上一个循环结束的更大的表示值开头。我们可以看到包含了每个可表示的值,因为任何规范表示( s , f , e )的值都出现在{{ 1}},其中f
的值为 e 。我们无法看到任何重复的值,因为每个可表示的值在其规范表示中仅被处理了一次。
要将其限制为特定的上下限 L 和 U ,我们可以找到 L 和 U的规范表示形式。这些表示的组成部分告诉我们e
和f
的开始和结束位置。该算法的替代形式可能更适合于此。假设e
和fL
是 L 的规范表示的 e 和 f ,对于{{ 1}}和eL
。那么一个算法是:
(0) Set s to 0, f to fL, and e to eL. (1) If e ≤ eU and f > fU, stop. (2) Process (s, f, e) as a decimal number. (3) Set f to f+1. (4) If f is less than 2^96, go to (1). (5) Set e to e-1 and f to f/10. (6) Go to (1).
对负数的扩展是显而易见的。