# Floating-point Approximation in Golang

## The challenge

Consider the function

`f: x -> sqrt(1 + x) - 1` at `x = 1e-15`.

We get: `f(x) = 4.44089209850062616e-16`

This function involves the subtraction of a pair of similar numbers when x is near 0 and the results are significantly erroneous in this region. Using `pow` instead of `sqrt` doesn’t give better results.

A “good” answer is `4.99999999999999875... * 1e-16`.

Can you modify f(x) to give a good approximation of f(x) in the neighborhood of 0?

## The solution in Golang

Option 1:

```.wp-block-code{border:0;padding:0}.wp-block-code>div{overflow:auto}.shcb-language{border:0;clip:rect(1px,1px,1px,1px);-webkit-clip-path:inset(50%);clip-path:inset(50%);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px;word-wrap:normal;word-break:normal}.hljs{box-sizing:border-box}.hljs.shcb-code-table{display:table;width:100%}.hljs.shcb-code-table>.shcb-loc{color:inherit;display:table-row;width:100%}.hljs.shcb-code-table .shcb-loc>span{display:table-cell}.wp-block-code code.hljs:not(.shcb-wrap-lines){white-space:pre}.wp-block-code code.hljs.shcb-wrap-lines{white-space:pre-wrap}.hljs.shcb-line-numbers{border-spacing:0;counter-reset:line}.hljs.shcb-line-numbers>.shcb-loc{counter-increment:line}.hljs.shcb-line-numbers .shcb-loc>span{padding-left:.75em}.hljs.shcb-line-numbers .shcb-loc::before{border-right:1px solid #ddd;content:counter(line);display:table-cell;padding:0 .75em;text-align:right;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;white-space:nowrap;width:1%}```package solution
import (
"math"
)
func F(x float64) float64 {
return x / (1.0 + math.Sqrt(1.0 + x))
}
```Code language: Go (go)```

Option 2:

``````package solution
func F(x float64) float64 {
return x*(0.5 - x*(0.125 - x*(0.0625 - x*0.0390625)))
}
```Code language: Go (go)```

Option 3:

``````package solution
import "math/big"
func F(x float64) float64 {
var a, b, c, d, e big.Float
a.SetInt64(1)
b.SetFloat64(x)
c.SetPrec(106)
d.Sqrt(&c)
e.Sub(&d, &a)
r, _ := e.Float64()
return r
}
```Code language: Go (go)```

## Test cases to validate our solution

``````package solution_test
import (
. "github.com/onsi/ginkgo"
. "github.com/onsi/gomega"
"math"
"fmt"
)
func assertFuzzyEquals(act float64, exp float64) {
var inrange bool
var merr float64 = 1e-12
var e float64
if (exp == 0.0) {
e = math.Abs(act)
} else {
e = math.Abs((act - exp) / exp)
}
inrange = (e <= merr)
if (inrange == false) {
fmt.Printf("Expected should be near: %1.12e , but got: %1.12e\n", exp ,act);
}
Expect(inrange).To(Equal(true))
}
func dotest(x float64, exp float64) {
assertFuzzyEquals(F(x), exp)
}
var _ = Describe("Test Example", func() {
It("should handle basic cases", func() {
dotest(2.6e-08, 1.29999999155e-08)
dotest(1.4e-09, 6.999999997549999e-10)
dotest(5.0e-06, 2.499996875007812e-06)
})
})
```Code language: Go (go)```
Tags:
Subscribe
Notify of