Why doesn't Go have a function to calculate the absolute value of integers?
Asked Answered
I

4

36

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))  
}
Impersonalize answered 25/8, 2019 at 19:5 Comment(1)
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.Shoshone
D
25

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.

Delanie answered 25/8, 2019 at 20:35 Comment(2)
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.Spear
Agree with @Spear - 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?Runofthemill
Q
12

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
Quadrennium answered 6/7, 2021 at 21:40 Comment(0)
D
4

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
}
Delila answered 9/8, 2023 at 8:2 Comment(2)
Or use the ~ annotation to write this for all types of integer to have only one functionCohesive
@Cohesive even better: Use T constraints.Signed - will work for floating-point types as well.Huddleston
E
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)
Elianore answered 4/1, 2020 at 14:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.