Documentation
¶
Overview ¶
Package sqrt computes square roots and cube roots to arbitrary precision.
Number is the main type in this package. It represents a lazily evaluated non negative real number that generally has an infinite number of digits, but a Number can also have a finite number of digits.
A FiniteNumber works like Number except that it always has a finite number of digits. A *FiniteNumber can be used anywhere a Number type is expected but not the other way around.
A Sequence is a view of a contiguous subset of digits of a Number. For example, A Sequence could represent everything past the 1000th digit of the square root of 3. Because Sequences are views, they are cheap to create. Note that Number and *FiniteNumber can be used anywhere a Sequence type is expected. A Sequence can be either infinite or finite in length.
A FiniteSequence works like Sequence except unlike Sequence, a FiniteSequence is always finite in length. A FiniteSequence can be used anywhere a Sequence is expected, and a *FiniteNumber can be used anywhere a FiniteSequence is expected. However, a Number or Sequence cannot be used where a FiniteSequence is expected because they can have an infinite number of digits. A FiniteSequence must have a finite number of digits.
Index ¶
- func AsString(s FiniteSequence) string
- type FiniteNumber
- func (n *FiniteNumber) All() iter.Seq2[int, int]
- func (n *FiniteNumber) AllInRange(start, end int) iter.Seq2[int, int]
- func (n *FiniteNumber) At(posit int) int
- func (n *FiniteNumber) Backward() iter.Seq2[int, int]
- func (n *FiniteNumber) Exact() string
- func (n *FiniteNumber) Exponent() int
- func (n *FiniteNumber) FiniteWithStart(start int) FiniteSequence
- func (n *FiniteNumber) Format(state fmt.State, verb rune)
- func (n *FiniteNumber) IsZero() bool
- func (n *FiniteNumber) String() string
- func (n *FiniteNumber) Values() iter.Seq[int]
- func (n *FiniteNumber) WithEnd(end int) FiniteSequence
- func (n *FiniteNumber) WithSignificant(limit int) *FiniteNumber
- func (n *FiniteNumber) WithStart(start int) Sequence
- type FiniteSequence
- type Generator
- type Number
- func CubeRoot(radican int64) Number
- func CubeRootBigInt(radican *big.Int) Number
- func CubeRootBigRat(radican *big.Rat) Number
- func CubeRootRat(num, denom int64) Number
- func NewNumber(g Generator) Number
- func NewNumberForTesting(fixed, repeating []int, exp int) (Number, error)
- func Sqrt(radican int64) Number
- func SqrtBigInt(radican *big.Int) Number
- func SqrtBigRat(radican *big.Rat) Number
- func SqrtRat(num, denom int64) Number
- type Sequence
Examples ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func AsString ¶
func AsString(s FiniteSequence) string
AsString returns all the digits in s as a string.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// sqrt(3) = 0.1732050807... * 10^1
n := sqrt.Sqrt(3)
fmt.Println(sqrt.AsString(n.WithStart(2).WithEnd(10)))
}
Output: 32050807
Types ¶
type FiniteNumber ¶
type FiniteNumber struct {
// contains filtered or unexported fields
}
FiniteNumber is a Number with a finite number of digits. FiniteNumber implements both Number and FiniteSequence. The zero value for FiniteNumber is 0.
Pass FiniteNumber instances by reference not by value. Copying a FiniteNumber instance is not supported and may cause errors.
func NewFiniteNumber ¶
func NewFiniteNumber(fixed []int, exponent int) (*FiniteNumber, error)
NewFiniteNumber works like NewNumberForTesting except that it returns a *FiniteNumber instead of a Number. Note that there is no repeating parameter because FiniteNumbers have a finite number of digits.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// n = 563.5
n, _ := sqrt.NewFiniteNumber([]int{5, 6, 3, 5}, 3)
fmt.Println(n.Exact())
}
Output: 563.5
func (*FiniteNumber) All ¶
func (n *FiniteNumber) All() iter.Seq2[int, int]
All comes from the Sequence interface.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// sqrt(7) = 0.26457513110... * 10^1
n := sqrt.Sqrt(7)
for index, value := range n.All() {
fmt.Println(index, value)
if index == 5 {
break
}
}
}
Output: 0 2 1 6 2 4 3 5 4 7 5 5
func (*FiniteNumber) AllInRange ¶
AllInRange comes from the Sequence interface.
func (*FiniteNumber) At ¶
func (n *FiniteNumber) At(posit int) int
At comes from the Number interface.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// sqrt(7) = 0.264575131106459...*10^1
n := sqrt.Sqrt(7)
fmt.Println(n.At(0))
fmt.Println(n.At(1))
fmt.Println(n.At(2))
}
Output: 2 6 4
func (*FiniteNumber) Backward ¶
func (n *FiniteNumber) Backward() iter.Seq2[int, int]
Backward comes from the FiniteSequence interface.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// sqrt(7) = 0.26457513110... * 10^1
n := sqrt.Sqrt(7).WithSignificant(6)
for index, value := range n.Backward() {
fmt.Println(index, value)
}
}
Output: 5 5 4 7 3 5 2 4 1 6 0 2
func (*FiniteNumber) Exact ¶
func (n *FiniteNumber) Exact() string
Exact works like String, but uses enough significant digits to return the exact representation of n.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
n := sqrt.Sqrt(2).WithSignificant(60)
fmt.Println(n.Exact())
}
Output: 1.41421356237309504880168872420969807856967187537694807317667
func (*FiniteNumber) Exponent ¶
func (n *FiniteNumber) Exponent() int
Exponent comes from the Number interface.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// sqrt(50176) = 0.224 * 10^3
n := sqrt.Sqrt(50176)
fmt.Println(n.Exponent())
}
Output: 3
func (*FiniteNumber) FiniteWithStart ¶
func (n *FiniteNumber) FiniteWithStart(start int) FiniteSequence
FiniteWithStart comes from the FiniteSequence interface.
func (*FiniteNumber) Format ¶
func (n *FiniteNumber) Format(state fmt.State, verb rune)
Format comes from the Number interface.
func (*FiniteNumber) IsZero ¶
func (n *FiniteNumber) IsZero() bool
IsZero comes from the Number interface.
func (*FiniteNumber) String ¶
func (n *FiniteNumber) String() string
String comes from the Number interface.
func (*FiniteNumber) Values ¶
func (n *FiniteNumber) Values() iter.Seq[int]
Values comes from the Sequence interface.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// sqrt(7) = 0.26457513110... * 10^1
n := sqrt.Sqrt(7)
for value := range n.WithEnd(6).Values() {
fmt.Println(value)
}
}
Output: 2 6 4 5 7 5
func (*FiniteNumber) WithEnd ¶
func (n *FiniteNumber) WithEnd(end int) FiniteSequence
WithEnd comes from the Sequence interface.
func (*FiniteNumber) WithSignificant ¶
func (n *FiniteNumber) WithSignificant(limit int) *FiniteNumber
WithSignificant comes from the Number interface.
func (*FiniteNumber) WithStart ¶
func (n *FiniteNumber) WithStart(start int) Sequence
WithStart comes from the Sequence interface.
type FiniteSequence ¶
type FiniteSequence interface {
Sequence
// Backward returns the 0 based position and value of each digit in this
// FiniteSequence from end to beginning.
Backward() iter.Seq2[int, int]
// FiniteWithStart works like WithStart except that it returns a
// FiniteSequence.
FiniteWithStart(start int) FiniteSequence
}
FiniteSequence represents a Sequence of finite length.
type Generator ¶
type Generator interface {
// Generate returns the digits of the mantissa and the exponent for a
// Number. Numbers are of the form mantissa*10^exp where mantissa is
// is between 0.1 inclusive and 1.0 exclusive. Calling digits() returns
// each digit of the mantissa in turn. The first call to digits() cannot
// return 0 because of the range of values a mantissa can have. If a
// call to digits() returns -1, this means that there are no more digits
// in the mantissa. If the first call to digits() return -1, that means
// that the resulting Number is zero. Once a call to digits() returns -1,
// all successive calls to digits() must also return -1. digits() must
// return values between 0 and 9 or -1.
Generate() (digits func() int, exp int)
}
Interface Generator lazily generates the digits of a Number.
type Number ¶
type Number interface {
Sequence
// At returns the significant digit of this Number at the given 0 based
// position. If this Number has posit or fewer significant digits, At
// returns -1. If posit is negative, At returns -1.
At(posit int) int
// WithSignificant returns a view of this Number that has no more than
// limit significant digits. WithSignificant rounds the returned value
// down toward zero. WithSignificant panics if limit is negative.
WithSignificant(limit int) *FiniteNumber
// Exponent returns the exponent of this Number.
Exponent() int
// Format prints this Number with the f, F, g, G, e, E verbs. The
// verbs work in the usual way except that they always round down.
// Because Number can have an infinite number of digits, g with no
// precision shows a max of 16 significant digits. Format supports
// width, precision, and the '-' flag for left justification. The v
// verb is an alias for g.
Format(state fmt.State, verb rune)
// String returns the decimal representation of this Number using %g.
String() string
// IsZero returns true if this Number is zero.
IsZero() bool
// contains filtered or unexported methods
}
Number is a reference to a non-negative real number. A non-zero Number is of the form mantissa * 10^exponent where mantissa is between 0.1 inclusive and 1.0 exclusive. A Number can represent either a finite or infinite number of digits. A Number computes the digits of its mantissa lazily on an as needed basis. To compute a given digit, a Number must compute all digits that come before that digit. A Number stores its computed digits so that they only have to be computed once. Number instances are safe to use with multiple goroutines.
The Number factory functions such as the Sqrt and CubeRoot functions return new Number instances that contain no computed digits initially.
Because Number instances store their computed digits, it is best to reuse a Number instance when possible. For example the code:
n := sqrt.Sqrt(6) fmt.Println(n.At(10000)) fmt.Println(n.At(10001))
runs faster than the code:
fmt.Println(sqrt.Sqrt(6).At(10000)) fmt.Println(sqrt.Sqrt(6).At(10001))
In the first code block, the second line reuses digits computed in the first line, but in the second code block, no reuse is possible since sqrt.Sqrt(6) always returns a Number with no precomputed digits.
A Number can be 0, in which case IsZero() returns true. Zero Numbers have an exponent of 0 and no digits in their mantissa. This means that calling At() on a zero Number always returns -1. Likewise calling All() or Values() on a zero Number returns an empty iterator. However, calling String() on a zero Number returns "0" and printing a zero Number prints 0 according to the format specification used.
func CubeRoot ¶
CubeRoot returns the cube root of radican. CubeRoot panics if radican is negative as Number can only hold positive results.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// Print the cube root of 3 with 100 significant digits.
fmt.Printf("%.100g\n", sqrt.CubeRoot(3))
}
Output: 1.442249570307408382321638310780109588391869253499350577546416194541687596829997339854755479705645256
func CubeRootBigInt ¶
CubeRootBigInt returns the cube root of radican. CubeRootBigInt panics if radican is negative as Number can only hold positive results.
func CubeRootBigRat ¶
CubeRootBigRat returns the cube root of radican. Because Number can only hold positive results, the denominator of radican must be positive, and the numerator must be non-negative or else CubeRootBigRat panics.
func CubeRootRat ¶
CubeRootRat returns the cube root of num / denom. Because Number can only hold positive results, denom must be positive, and num must be non-negative or else CubeRootRat panics.
func NewNumber ¶
NewNumber returns a new Number based on g. Although g is expected to follow the contract of Generator, if g yields mantissa digits outside the range of 0 and 9, NewNumber regards that as a signal that there are no more mantissa digits. Also if g happens to yield 0 as the first digit of the mantissa, NewNumber will return zero.
func NewNumberForTesting ¶
NewNumberForTesting creates an arbitrary Number for testing. fixed are digits between 0 and 9 representing the non repeating digits that come immediately after the decimal place of the mantissa. repeating are digits between 0 and 9 representing the repeating digits that follow the non repeating digits of the mantissa. exp is the exponent part of the returned Number. NewNumberForTesting returns an error if fixed or repeating contain values not between 0 and 9, or if the first digit of the mantissa would be zero since mantissas must be between 0.1 inclusive and 1.0 exclusive.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// n = 10.2003400340034...
n, _ := sqrt.NewNumberForTesting([]int{1, 0, 2}, []int{0, 0, 3, 4}, 2)
fmt.Println(n)
}
Output: 10.20034003400340
func Sqrt ¶
Sqrt returns the square root of radican. Sqrt panics if radican is negative.
Example ¶
package main
import (
"fmt"
"github.com/keep94/sqrt"
)
func main() {
// Print the square root of 13 with 100 significant digits.
fmt.Printf("%.100g\n", sqrt.Sqrt(13))
}
Output: 3.605551275463989293119221267470495946251296573845246212710453056227166948293010445204619082018490717
func SqrtBigInt ¶
SqrtBigInt returns the square root of radican. SqrtBigInt panics if radican is negative.
func SqrtBigRat ¶
SqrtBigRat returns the square root of radican. The denominator of radican must be positive, and the numerator must be non-negative or else SqrtBigRat panics.
type Sequence ¶
type Sequence interface {
// All returns the 0 based position and value of each digit in this
// Sequence from beginning to end.
All() iter.Seq2[int, int]
// AllInRange returns the 0 based position and value of each digit in
// this sequence from position start up to but not including position
// end.
AllInRange(start, end int) iter.Seq2[int, int]
// Values returns the value of each digit in this Sequence from
// beginning to end.
Values() iter.Seq[int]
// WithStart returns a view of this Sequence that only has digits with
// zero based positions greater than or equal to start.
WithStart(start int) Sequence
// WithEnd returns a view of this Sequence that only has digits with
// zero based positions less than end.
WithEnd(end int) FiniteSequence
// contains filtered or unexported methods
}
Sequence represents a sequence of digits of either finite or infinite length within the mantissa of a real number. Although they can start and optionally end anywhere within a mantissa, Sequences must be contiguous. That is they can have no gaps in the middle.