范围函数未通过所有测试

问题描述

我正在编写一个范围函数,它应该返回指定范围内的整数列表。

range(2,12,3) 应该返回列表 [2,5,8,11]

range(10,2,~1) 应该返回列表 [10,9,7,6,4,3]

对于 range(2,3) 这有效:

fun range(start,stop,step) =
if start > stop then nil
else start::range(start+step,step);

对于 range(10,~1) 这有效:

fun range(start,step) =
if start <= stop then nil
else start::range(start+step,step);

但是,我需要一个函数来处理这两种情况。我尝试使用 orelse 和 else if 如下,但该函数返回一个空列表。

奥雷尔:

fun range(start,step) =
if start > stop orelse start <= stop then nil
else start::range(start+step,step);

否则如果:

fun range(start,step) =
if start > stop then nil
else if start <= stop then nil
else start::range(start+step,step);

两种方法都返回

val it = [] : int list

我认为这与在基本情况下使用 nil 有关,但我不知道为什么。

需要更改什么才能使函数返回两个测试的预期输出

谢谢

解决方法

不要将 stopstart 进行比较,而是考虑 stop - start 的符号和 step 的符号。
如果你想一想,你会发现只要你在这个范围内,符号都是一样的。

fun sgn x = if x < 0 
            then ~1 
            else if x > 0 
                 then 1 
                 else 0;

fun range (start,stop,step) = if sgn(stop-start) = sgn(step)
                                then start :: range (start + step,step)
                                else []
,

问题:

在您的两个解决方案中,条件将始终为 true,因为您正在检查 start 是否小于、大于或等于 stop,这是对任何一对数字都为真。

解决方案:

您必须根据step的符号检查当前情况。

如果 step 为零,则不要检查其他任何内容,因为无法创建步骤 0 的范围。抛出异常将是一个不错的选择。

如果 step 为正,请检查 start 是否低于 stop。如果没有,请停止。

如果 step 为负数,请检查 start 是否高于 stop。如果没有,请停止。

完整代码:

fun range(start,step) =
if start = stop orelse
(start < stop andalso step < 0) orelse
(start > stop andalso step > 0) then nil
else start::range(start+step,step);