在 OCaml 中对类型 int 数组数组进行乘法 table
Making a multiplication table of type int array array in OCaml
我正在学习 OCaml 命令式编程的一些基础知识。
我正在尝试制作一个简单的 int 数组数组,其中包含乘法 table 直到我作为参数传递的整数。
例如 table 2
的输出预计为 return
[|[|1;2|];[|2;4|]|]
我的代码不起作用。我首先用足够的 space 初始化一个数组并用零填充它。 x
的迭代适用于数组的索引,因为数组的每个条目都被填充但是 (x+1) * (y+1)
部分有问题。
table 2
的结果是 [|[|2;4|];[|2;4|]|]
,好像它没有正确迭代 x。
提供的答案有效。我不知道为什么——因为我们似乎在做同样的事情。我们用足够的 space 初始化一个数组,并用零填充它。然后我们使用嵌套的 for 循环来填充它。是因为答案使用了第一个 for 循环吗?为什么呢?
我的代码:
let table n =
let a = Array.make n (Array.make n 0) in
for x = 0 to n-1 do
for y = 0 to n-1 do
a.(x).(y) <- ((x+1) * (y+1));
done;
done;
a;;
答案:
let table n =
let a = Array.make n [||] in
for x = 0 to n-1 do
a.(x) <- Array.make n 0
done;
for y = 0 to n-1 do
for x = 0 to n-1 do
a.(x).(y) <- (x+1)*(y+1)
done
done;
a;;
您的问题是 Array.make
将用相同的单个值填充数组。因此,您的外部数组不包含 n
个不同的数组,而是 n
个对同一数组的引用。
您将使用以下代码得到相同的意外结果:
let aa = Array.make n 0 in
let a = Array.make n [||] in
for x = 0 to n - 1 do
a.(x) <- aa
done
编写工作示例是为了避免这个问题。首先,它创建一个包含 n
个空数组 [||]
副本的外部数组,然后通过调用 n
不同的 数组对象填充它 Array.make
每一个。
要调整您的代码,您可以改用 Array.init
,它会为每个不同的数组元素调用指定的函数:
let a = Array.init n (fun _ -> Array.make n 0)
或者您可以使用 Array.make_matrix
:
let a = Array.make_matrix n n 0
更新
在示例中使用 ref 5
而不是 0
并没有真正改变任何东西,只是 ref 5
本身是可变的。假设我们不打算修改引用,而只是更改内部数组的内容。然后你会看到这样的东西:
# let a = Array.make 3 (Array.make 3 (ref 5));;
val a : int ref array array =
[|[|{contents = 5}; {contents = 5}; {contents = 5}|];
[|{contents = 5}; {contents = 5}; {contents = 5}|];
[|{contents = 5}; {contents = 5}; {contents = 5}|]|]
# a.(1).(2) <- ref 88;;
- : unit = ()
# a;;
- : int ref array array =
[|[|{contents = 5}; {contents = 5}; {contents = 88}|];
[|{contents = 5}; {contents = 5}; {contents = 88}|];
[|{contents = 5}; {contents = 5}; {contents = 88}|]|]
如您所见,所有内部数组似乎都发生了变化。那是因为只有一个内部数组。所以实际上只有一个数组发生了变化。外部数组的所有 3 个元素都包含这个数组。
接下来,请注意只有一次调用 ref 5
。这意味着所有参考文献(全部 9 个)都是相同的参考文献。您可以在以下内容中看到这一点:
# let a = Array.make 3 (Array.make 3 (ref 5));;
val a : int ref array array =
[|[|{contents = 5}; {contents = 5}; {contents = 5}|];
[|{contents = 5}; {contents = 5}; {contents = 5}|];
[|{contents = 5}; {contents = 5}; {contents = 5}|]|]
# a.(1).(2) := 99;;
- : unit = ()
# a;;
- : int ref array array =
[|[|{contents = 99}; {contents = 99}; {contents = 99}|];
[|{contents = 99}; {contents = 99}; {contents = 99}|];
[|{contents = 99}; {contents = 99}; {contents = 99}|]|]
不出所料,所有元素都变成了 99,因为只有一个引用出现在所有 9 个位置。
如果您想解释其他示例代码,可以在上面添加它们。如果它们很复杂,最好 post 一个新问题。
我正在学习 OCaml 命令式编程的一些基础知识。
我正在尝试制作一个简单的 int 数组数组,其中包含乘法 table 直到我作为参数传递的整数。
例如 table 2
的输出预计为 return
[|[|1;2|];[|2;4|]|]
我的代码不起作用。我首先用足够的 space 初始化一个数组并用零填充它。 x
的迭代适用于数组的索引,因为数组的每个条目都被填充但是 (x+1) * (y+1)
部分有问题。
table 2
的结果是 [|[|2;4|];[|2;4|]|]
,好像它没有正确迭代 x。
提供的答案有效。我不知道为什么——因为我们似乎在做同样的事情。我们用足够的 space 初始化一个数组,并用零填充它。然后我们使用嵌套的 for 循环来填充它。是因为答案使用了第一个 for 循环吗?为什么呢?
我的代码:
let table n =
let a = Array.make n (Array.make n 0) in
for x = 0 to n-1 do
for y = 0 to n-1 do
a.(x).(y) <- ((x+1) * (y+1));
done;
done;
a;;
答案:
let table n =
let a = Array.make n [||] in
for x = 0 to n-1 do
a.(x) <- Array.make n 0
done;
for y = 0 to n-1 do
for x = 0 to n-1 do
a.(x).(y) <- (x+1)*(y+1)
done
done;
a;;
您的问题是 Array.make
将用相同的单个值填充数组。因此,您的外部数组不包含 n
个不同的数组,而是 n
个对同一数组的引用。
您将使用以下代码得到相同的意外结果:
let aa = Array.make n 0 in
let a = Array.make n [||] in
for x = 0 to n - 1 do
a.(x) <- aa
done
编写工作示例是为了避免这个问题。首先,它创建一个包含 n
个空数组 [||]
副本的外部数组,然后通过调用 n
不同的 数组对象填充它 Array.make
每一个。
要调整您的代码,您可以改用 Array.init
,它会为每个不同的数组元素调用指定的函数:
let a = Array.init n (fun _ -> Array.make n 0)
或者您可以使用 Array.make_matrix
:
let a = Array.make_matrix n n 0
更新
在示例中使用 ref 5
而不是 0
并没有真正改变任何东西,只是 ref 5
本身是可变的。假设我们不打算修改引用,而只是更改内部数组的内容。然后你会看到这样的东西:
# let a = Array.make 3 (Array.make 3 (ref 5));;
val a : int ref array array =
[|[|{contents = 5}; {contents = 5}; {contents = 5}|];
[|{contents = 5}; {contents = 5}; {contents = 5}|];
[|{contents = 5}; {contents = 5}; {contents = 5}|]|]
# a.(1).(2) <- ref 88;;
- : unit = ()
# a;;
- : int ref array array =
[|[|{contents = 5}; {contents = 5}; {contents = 88}|];
[|{contents = 5}; {contents = 5}; {contents = 88}|];
[|{contents = 5}; {contents = 5}; {contents = 88}|]|]
如您所见,所有内部数组似乎都发生了变化。那是因为只有一个内部数组。所以实际上只有一个数组发生了变化。外部数组的所有 3 个元素都包含这个数组。
接下来,请注意只有一次调用 ref 5
。这意味着所有参考文献(全部 9 个)都是相同的参考文献。您可以在以下内容中看到这一点:
# let a = Array.make 3 (Array.make 3 (ref 5));;
val a : int ref array array =
[|[|{contents = 5}; {contents = 5}; {contents = 5}|];
[|{contents = 5}; {contents = 5}; {contents = 5}|];
[|{contents = 5}; {contents = 5}; {contents = 5}|]|]
# a.(1).(2) := 99;;
- : unit = ()
# a;;
- : int ref array array =
[|[|{contents = 99}; {contents = 99}; {contents = 99}|];
[|{contents = 99}; {contents = 99}; {contents = 99}|];
[|{contents = 99}; {contents = 99}; {contents = 99}|]|]
不出所料,所有元素都变成了 99,因为只有一个引用出现在所有 9 个位置。
如果您想解释其他示例代码,可以在上面添加它们。如果它们很复杂,最好 post 一个新问题。