Arrays F#比较两个数组是否相等,以达到指定的精度级别

Arrays F#比较两个数组是否相等,以达到指定的精度级别,arrays,f#,multidimensional-array,precision,Arrays,F#,Multidimensional Array,Precision,下面是我要翻译的C代码: public bool equals(Matrix matrix, int precision) { if (precision < 0) { throw new MatrixError("Precision can't be a negative number."); } double test = Math.Pow(10.0, precision);

下面是我要翻译的C代码:

public bool equals(Matrix matrix, int precision)
    {

        if (precision < 0)
        {
            throw new MatrixError("Precision can't be a negative number.");
        }

        double test = Math.Pow(10.0, precision);
        if (double.IsInfinity(test) || (test > long.MaxValue))
        {
            throw new MatrixError("Precision of " + precision
                    + " decimal places is not supported.");
        }

        precision = (int)Math.Pow(10, precision);

        for (int r = 0; r < this.Rows; r++)
        {
            for (int c = 0; c < this.Cols; c++)
            {
                if ((long)(this[r, c] * precision) != (long)(matrix[r, c] * precision))
                {
                    return false;
                }
            }
        }

        return true;
    }
public bool equals(矩阵,整数精度)
{
if(精度<0)
{
抛出新矩阵错误(“精度不能是负数”);
}
双重测试=数学功率(10.0,精度);
if(double.IsInfinity(test)| |(test>long.MaxValue))
{
抛出新矩阵错误(“精度”+精度
+“不支持小数位。”);
}
精度=(int)Math.Pow(10,精度);
for(int r=0;r
以下是我到目前为止的情况:

类型矩阵(sourceMatrix:double[,])=
让rows=sourceMatrix.GetUpperBound(0)+1
设cols=sourceMatrix.GetUpperBound(1)+1
让matrix=Array2D.zeroCreate rows cols
做
因为我在0。。行-1 do
对于0中的j。。cols-1 do
矩阵[i,j]double(System.Int32.MaxValue)),然后引发(新的ArgumentOutOfRangeException(“精度为“+精度.ToString()+”小数位数不受支持”)
设精度=int(数学功率(10.0,双精度)))

正如您所看到的,到目前为止,我编写的代码中都加载了类型转换,这可能意味着我的代码没有按应有的方式编写。未完成的部分需要在第一个元素上返回方法,该元素在计算到一定精度时返回false。我相信一定有一些优雅的F#代码来实现这一点,显然我离它还差得远。我试图弄清楚Array2D类是否有允许我这样做的方法,但如果有,我无法找到它。我知道PowerPack Matrix类,并最终会使用它,但现在我正试图通过将我理解的C代码翻译成F来学习F。说起来容易做起来难。:)我相信我已经在我创建的类型中添加了所有相关的F#代码。如果我遗漏了什么,请告诉我。

写这篇文章的一种优雅而高级的方法可能不会非常有效,那就是使用惰性序列表达式:

seq { for r in 0 .. this.Rows - 1 do
        for c in 0 .. this.Cols - 1 do
          if <your condition goes here> then
            yield false}
|> Seq.forall id

写这篇文章的一种优雅而高级的方法可能不会非常有效,那就是使用惰性序列表达式:

seq { for r in 0 .. this.Rows - 1 do
        for c in 0 .. this.Cols - 1 do
          if <your condition goes here> then
            yield false}
|> Seq.forall id

以下是您代码的自由翻译:

type Matrix(sourceMatrix) =
    let rows = Array2D.length1 sourceMatrix
    let cols = Array2D.length2 sourceMatrix
    let matrix = Array2D.copy sourceMatrix

    ///The number of Rows in this Matrix.
    member this.Rows = rows

    ///The number of Columns in this Matrix.
    member this.Cols = cols

    ///Retrieve data from this Matrix
    member this.Item(x,y) = matrix.[x,y]

    member this.Equals(matrix:Matrix, precision) =
        if precision < 0 then failwith "Precision can't be a negative number."
        let precision = 10.0 ** double(precision)
        if Double.IsInfinity(precision) then failwith ("Precision of " + string(precision) + " decimal places is not supported.")
        seq {
            for r in 0 .. rows - 1 do
                for c in 0 .. cols - 1 do
                    if floor(matrix.[r, c] * precision) <>
                       floor(this.[r, c] * precision) then
                        yield false
        } |> Seq.forall id
类型矩阵(sourceMatrix)=
让rows=Array2D.length1 sourceMatrix
设cols=Array2D.length2 sourceMatrix
让matrix=Array2D.copy sourceMatrix
///此矩阵中的行数。
成员this.Rows=Rows
///此矩阵中的列数。
成员:this.Cols=Cols
///从该矩阵检索数据
成员。项目(x,y)=矩阵。[x,y]
成员this.Equals(矩阵:矩阵,精度)=
如果精度<0,则“精度不能为负数”失败
让精度=10.0**双倍(精度)
如果是Double.IsInfinity(precision),则failwith(“不支持“+字符串(precision)+”小数位的精度”)
序号{
对于0..行中的r-1 do
对于0..cols-1 do中的c
if地板(矩阵[r,c]*精度)
地板(此[r,c]*精度)然后
假屈服
}|>所有id的顺序
请注意我是如何将数组方法调用更改为
Array2D
函数调用的,这稍微清理了一下。然后我添加了一个索引器(
this.Item
),以便您可以从矩阵中实际读取数据

您会注意到,我通过调用
floor
,改变了整数转换的用法,这就消除了在整数和浮点之间转换的许多需要


正如Thomas所建议的,比较是在惰性序列中进行的。

下面是代码的自由翻译:

type Matrix(sourceMatrix) =
    let rows = Array2D.length1 sourceMatrix
    let cols = Array2D.length2 sourceMatrix
    let matrix = Array2D.copy sourceMatrix

    ///The number of Rows in this Matrix.
    member this.Rows = rows

    ///The number of Columns in this Matrix.
    member this.Cols = cols

    ///Retrieve data from this Matrix
    member this.Item(x,y) = matrix.[x,y]

    member this.Equals(matrix:Matrix, precision) =
        if precision < 0 then failwith "Precision can't be a negative number."
        let precision = 10.0 ** double(precision)
        if Double.IsInfinity(precision) then failwith ("Precision of " + string(precision) + " decimal places is not supported.")
        seq {
            for r in 0 .. rows - 1 do
                for c in 0 .. cols - 1 do
                    if floor(matrix.[r, c] * precision) <>
                       floor(this.[r, c] * precision) then
                        yield false
        } |> Seq.forall id
类型矩阵(sourceMatrix)=
让rows=Array2D.length1 sourceMatrix
设cols=Array2D.length2 sourceMatrix
让matrix=Array2D.copy sourceMatrix
///此矩阵中的行数。
成员this.Rows=Rows
///此矩阵中的列数。
成员:this.Cols=Cols
///从该矩阵检索数据
成员。项目(x,y)=矩阵。[x,y]
成员this.Equals(矩阵:矩阵,精度)=
如果精度<0,则“精度不能为负数”失败
让精度=10.0**双倍(精度)
如果是Double.IsInfinity(precision),则failwith(“不支持“+字符串(precision)+”小数位的精度”)
序号{
对于0..行中的r-1 do
对于0..cols-1 do中的c
if地板(矩阵[r,c]*精度)
地板(此[r,c]*精度)然后
假屈服
}|>所有id的顺序
请注意我是如何将数组方法调用更改为
Array2D
函数调用的,这稍微清理了一下。然后我添加了一个索引器(
this.Item
),以便您可以从矩阵中实际读取数据

您会注意到,我通过调用
floor
,改变了整数转换的用法,这就消除了在整数和浮点之间转换的许多需要


正如Thomas所建议的,比较是在惰性序列中进行的。

我建议将C代码翻译成函数C(提示:使用LINQ),然后将其翻译成F。我建议将C代码翻译成函数C(提示:使用LINQ),然后再翻译成F。谢谢Tomas!我要花很长时间才能做到这一点。顺便说一下,我有一本你的书《真实世界函数式编程》,我强烈推荐。也许我需要再读一遍为什么使用
Seq.exi