28

In Go, why is there no function which directly calculates absolute value for integer datatypes? Currently all integer values have to be typecast to float64 and then passed to math.Abs(), which returns a float64, which again has to be typecast into an integer.

This code raises a ./prog.go:12:39: cannot use x (type int64) as type float64 in argument to math.Abs error because Go is a statically typed language, so it does not allow a different datatype:

package main

import (
    "fmt"
    "math"
)

func main() {
    fmt.Println("Hello, playground")
    var x int64 = -10
    
    fmt.Println("Abolute value ", math.Abs(x))  
}
Boris Verkhovskiy
  • 14,854
  • 11
  • 100
  • 103
Piyush Singal
  • 335
  • 1
  • 3
  • 7
  • 6
    Converting integers to floats to use the `math` package and then back to integers is almost never the correct thing to do. The only reason most of the simple `math` functions exists for `float64` is that floats often have a number of corner cases (e.g. involving NaN and infinities) that are annoying to get correct; integers don't have those issues. – Dave C Aug 26 '19 at 10:48

4 Answers4

22

From Go's FAQ,

The standard library's purpose is to support the runtime, connect to the operating system, and provide key functionality that many Go programs require, such as formatted I/O and networking. It also contains elements important for web programming, including cryptography and support for standards like HTTP, JSON, and XML.

There is no clear criterion that defines what is included because for a long time, this was the only Go library. There are criteria that define what gets added today, however.

New additions to the standard library are rare and the bar for inclusion is high. Code included in the standard library bears a large ongoing maintenance cost (often borne by those other than the original author), is subject to the Go 1 compatibility promise (blocking fixes to any flaws in the API), and is subject to the Go release schedule, preventing bug fixes from being available to users quickly.

Most new code should live outside of the standard library and be accessible via the go tool's go get command. Such code can have its own maintainers, release cycle, and compatibility guarantees. Users can find packages and read their documentation at godoc.org.

In response to how easy it is to create integer versions of the math package's float functions, Go team member Russ Cox once quipped,

Ceil, Floor, and Trunc are even easier!

A reasonable interpretation would be that since this function is trivial to write (if x < 0, x = -x), it does not meet the bar for inclusion. Compare with the float version:

func Abs(x float64) float64 {
    return Float64frombits(Float64bits(x) &^ (1 << 63))
}

This being useful but also not obvious is a compelling reason to include it in the standard library.

  • 8
    Whether or not the function is "trivial" (for someone) to implement, is probably not a good metric. A better metric would be to look at the chance of people getting this wrong. Given the problematic answers I have seen to this question and the fact that people write blog postings that try to answer this question, I would say that it warrants inclusion in the standard library because there is a good chance people will get this wrong. – borud Jul 05 '22 at 12:36
  • 3
    Agree with @borud - the purpose of building a programming language + an accompanying standard library isn't just "to provide functionality that is complicated" - why make every user of your standard library rewrite the same functions? – Tim Nov 29 '22 at 15:27
9

Absolute value is just a special case of absolute difference [1], where the second value is zero. Here is absolute value function for integers, as well as absolute difference function for integers. Bonus is absolute difference function for unsigned integers:

package math

func absInt(x int) int {
   return absDiffInt(x, 0)
}

func absDiffInt(x, y int) int {
   if x < y {
      return y - x
   }
   return x - y
}

func absDiffUint(x, y uint) uint {
   if x < y {
      return y - x
   }
   return x - y
}
  1. https://wikipedia.org/wiki/Absolute_difference
Zombo
  • 1
  • 62
  • 391
  • 407
  • this absolutely does not answer the question, why was "why it's not included in the stdlib", not "how to implement it". – xdavidliu Aug 09 '23 at 17:54
1

Though there is no standard function, you always can write it yourself or use third party solution. This package contains Abs functions for all builtin signed integer types. Usage (after go get):

import (
    "fmt"
    "github.com/adam-lavrik/go-imath/i64" // Functions for i64 type
)
...
x := int64(-2)
fmt.Println(i64.Abs(x)) // Output: 2
x = i64.Minimal // Minimal negative value of int64, has no positive pair
fmt.Println(i64.Absu(x)) // Output: 9223372036854775808 (result is converted to uint64)
gastrodon
  • 75
  • 3
  • 9
LoveRick
  • 85
  • 3
1

It is trivial, with generics it's even more trivial. Write it once for each integer type:

import "golang.org/x/exp/constraints"

func Abs[T constraints.Integer](x T) T {
    if x < 0 {
        return -x
    }
    return x
}
blackgreen
  • 34,072
  • 23
  • 111
  • 129