Newbie Scala question about simple math array operations

前端 未结 4 1362
自闭症患者
自闭症患者 2021-02-14 22:17

Newbie Scala Question:

Say I want to do this [Java code] in Scala:

public static double[] abs(double[] r, double[] im) {
  double t[] = new double[r.leng         


        
4条回答
  •  被撕碎了的回忆
    2021-02-14 23:07

    There isn't a easy way in Java to create generic numeric computational code; the libraries aren't there as you can see from oxbow's answer. Collections also are designed to take arbitrary types, which means that there's an overhead in working with primitives with them. So the fastest code (without careful bounds checking) is either:

    def abs(re: Array[Double], im: Array[Double]) = {
      val a = new Array[Double](re.length)
      var i = 0
      while (i < a.length) {
        a(i) = math.sqrt(re(i)*re(i) + im(i)*im(i))
        i += 1
      }
      a
    }
    

    or, tail-recursively:

    def abs(re: Array[Double], im: Array[Double]) = {
      def recurse(a: Array[Double], i: Int = 0): Array[Double] = {
        if (i < a.length) {
          a(i) = math.sqrt(re(i)*re(i) + im(i)*im(i))
          recurse(a, i+1)
        }
        else a
      }
      recurse(new Array[Double](re.length))
    }
    

    So, unfortunately, this code ends up not looking super-nice; the niceness comes once you package it in a handy complex number array library.

    If it turns out that you don't actually need highly efficient code, then

    def abs(re: Array[Double], im: Array[Double]) = {
      (re,im).zipped.map((i,j) => math.sqrt(i*i + j*j))
    }
    

    will do the trick compactly and conceptually clearly (once you understand how zipped works). The penalty in my hands is that this is about 2x slower. (Using List makes it 7x slower than while or tail recursion in my hands; List with zip makes it 20x slower; generics with arrays are 3x slower even without computing the square root.)

    (Edit: fixed timings to reflect a more typical use case.)

提交回复
热议问题