通过使用浮点值作为循环计数器来优化循环

时间:2016-04-19 07:48:21

标签: loops floating-point numeric

我需要执行一个循环

while (X) do Y

为N次,这是一个很大的数字。虽然循环体Y是相当快的,但测试X约占运行时间的70%。

我可以预先计算循环迭代次数N,因此不使用X作为条件,可以使用简单的For循环。

for (i=1 to N) do Y

但是,N可能会超过整数可以存储在计算机上的最大值,因此这不是一个选项。作为替代方案,我建议使用浮点变量F代替。由于N很大,很可能F不能完全等于N.因此,我将F计算为小于N的最大浮点数。这允许我运行

for (i=1 to F) do Y
while (X) do Y

大多数迭代不需要每次都测试X,只需要测试最后一个N-F。

问题是:我如何实现从1到F的for-Loop?简单地增加计数器或在每个步骤中将F减小1都是行不通的,因为数值误差会变得太大。我目前的解决方案是:

for (while F > MAXINT)
    for (i=1 to MAXINT)
        do Y
    F -= MAXINT
while (X) do Y

有没有更好的方法来解决这个问题?

1 个答案:

答案 0 :(得分:0)

数字错误是什么意思?浮点计数精确度在其精度范围内。 以下是使用以下数据类型的整数表示的最大值:

uint32max     = 4294967295
uint64max     = 18446744073709551615
float32intmax = 16777216
float64intmax = 9007199254740992

从0到最大值的每个整数都可以精确表示,没有数字错误。

如您所见,uint64可以使用最大的计数。接下来是float64,然后是uint32,最后是float32。

增加uint32 = 4294967295时会发生什么? 0

增加float32 = 16777216时会发生什么? 16777216

哪种行为更好?

您是否考虑过使用二维循环?如果N是1维循环的最大计数,那么N x N是2维循环的最大值,等等。如果最大计数小于MAXUINT x MAXUINT,则将N分解为:

N == M * MAXUINT + R;

,其中

M = N / MAXUINT;
R = N - M * MAXUINT;

然后

for (i = M; i--;) for (j = MAXUINT; j--;) DoStuff();
for (i = R; i--;) DoStuff();

如果MAXUINT * MAXUINT的数量不够大,可以添加3次,4次,......次循环。