2

I'm trying to get the max value from a diff, n[i] - n[i-1], timeseries. The first value is always zero from the slice, here is the code:

func MaxBelowZero(n ...float64) float64 {
var maxValue float64
if len(n) == 1 {
    return n[0]
} else if len(n) == 0 {
    return 0.
}
for i := range n {
    if i == 0 {
        maxValue = math.SmallestNonzeroFloat64
        continue
    }
    if maxValue < n[i] && n[i] < 0 {
        maxValue = n[i]
    }
}
return maxValue
}

var sliceTest = []float64{0, 1, 2, -1, -2, -10, 10, 20}
MaxBelowZero(sliceTest...)
Output: 5e-324

It supossed to be -1. What am I doing wrong? I would appreciate some help. The code in playground: link

JMaia
  • 79
  • 4

3 Answers3

5

math.SmallestNonzeroFloat64 is the number closest to 0 that is not 0, not the number furthest from zero. Try this:

go playground

func MaxBelowZero(values ...float64) float64 {
    if len(values) == 0 {
        return 0
    } else if len(values) == 1 {
        return values[0]
    }
    max := -math.MaxFloat64
    for _, n := range values {
        if n >= 0 {
            continue
        }
        if n > max {
            max = n
        }
    }
    return max
}
Clark McCauley
  • 1,342
  • 5
  • 16
1
func MaxBelowZero(n ...float64) float64 {
    maxValue := -math.MaxFloat64 // Initial value must be negative
    if len(n) == 1 {
        return n[0]
    } else if len(n) == 0 {
        return 0.
    }
    for i := 1; i < len(n); i++ {
        diff := n[i] - n[i-1] // Correct logic here
        if diff > maxValue && diff < 0 {
            maxValue = diff
        }
    }
    return maxValue
}
Mehmet Esen
  • 6,156
  • 3
  • 25
  • 44
  • 1
    Sorry but my other mistake was not saying that the slice is already had a diff transformation. Thank you for your help – JMaia Jun 28 '21 at 22:41
-1

You could reverse sort the slice, then find first negative number:

package main
import "sort"

func main() {
   a := []float64{0, 1, 2, -1, -2, -10, 10, 20}
   sort.Slice(a, func(d, e int) bool {
      return a[e] < a[d]
   })
   n := sort.Search(len(a), func(n int) bool {
      return a[n] < 0
   })
   println(a[n] == -1)
}

Or sort by sign, then by absolute value:

package main
import "math"

type sFunc func(a, b float64) bool

var sFuncs = []sFunc{
   func(a, b float64) bool {
      return math.Copysign(1, a) < math.Copysign(1, b)
   },
   func(a, b float64) bool {
      return math.Abs(a) < math.Abs(b)
   },
}

Result:

package main

import (
   "fmt"
   "sort"
)

func main() {
   floats := []float64{0, 1, 2, -1, -2, -10, 10, 20}
   sort.Slice(floats, func(a, b int) bool {
      fa, fb := floats[a], floats[b]
      for _, sf := range sFuncs {
         if sf(fa, fb) {
            return true
         }
         if sf(fb, fa) {
            break
         }
      }
      return false
   })
   fmt.Println(floats) // [-1 -2 -10 0 1 2 10 20]
}
Zombo
  • 1
  • 62
  • 391
  • 407
  • The performance of these isn't any better than O(n) right? You still have to iterate over the entire slice to sort it at least once, maybe more. Then you have to iterate over the negative half. This doesn’t seem any better then a single iteration of the entire slice. – Clark McCauley Jul 01 '21 at 13:22