BigDecimal - Crystal 1.11.2

# struct BigDecimal

- BigDecimal
- Number
- Value
- Object

##
Overview

A `BigDecimal` can represent arbitrarily large precision decimals.

It is internally represented by a pair of `BigInt` and `UInt64`: value and scale. Value contains the actual value, and scale tells the decimal point place. E.g. when value is `1234` and scale `2`, the result is `12.34`.

NOTE To use `BigDecimal`, you must explicitly import it with `require "big"`

The general idea and some of the arithmetic algorithms were adapted from the MIT/APACHE-licensed bigdecimal-rs.

##
Included Modules

- Comparable(BigDecimal)
- Comparable(BigRational)
- Comparable(Float)
- Comparable(Int)

##
Defined in:

big.cr
big/big_decimal.cr
big/number.cr

##
Constant Summary

DEFAULT_MAX_DIV_ITERATIONS = `100_u64`

  DEPRECATED Use `DEFAULT_PRECISION` instead

DEFAULT_PRECISION = `100_u64`

##
Constructors

- .new(value : BigInt, scale : UInt64)

  Creates a new `BigDecimal` from `BigInt` value and `UInt64` scale, which matches the internal representation.

- .new(num : Float)

  Creates a new `BigDecimal` from `Float`.

- .new(num : BigRational)

  Creates a new `BigDecimal` from `BigRational`.

- .new(num : BigDecimal)

  Returns num.

- .new(num : Int = 0, scale : Int = 0)

  Creates a new `BigDecimal` from `Int`.

- .new(str : String)

  Creates a new `BigDecimal` from a `String`.

##
Instance Method Summary

- #%(other : BigDecimal) : BigDecimal
- #%(other : Int)
- #*(other : BigDecimal) : BigDecimal
- #*(other : Number) : BigDecimal
- #**(other : Int) : BigDecimal

  Raises the decimal to the otherth power

- #+(other : BigDecimal) : BigDecimal
- #+(other : Number) : BigDecimal
- #-(other : BigDecimal) : BigDecimal
- #-(other : Number) : BigDecimal
- #- : BigDecimal
- #/(other : BigDecimal) : BigDecimal
- #/(other : BigInt) : BigDecimal
- #/(other : BigFloat) : BigDecimal
- #/(other : BigRational) : BigRational
- #/(other : Int8) : BigDecimal
- #/(other : UInt8) : BigDecimal
- #/(other : Int16) : BigDecimal
- #/(other : UInt16) : BigDecimal
- #/(other : Int32) : BigDecimal
- #/(other : UInt32) : BigDecimal
- #/(other : Int64) : BigDecimal
- #/(other : UInt64) : BigDecimal
- #/(other : Int128) : BigDecimal
- #/(other : UInt128) : BigDecimal
- #/(other : Float32) : BigDecimal
- #/(other : Float64) : BigDecimal
- #<=>(other : BigDecimal) : Int32

  The comparison operator.

- #<=>(other : BigRational) : Int32
- #<=>(other : Float::Primitive) : Int32 | Nil
- #<=>(other : BigFloat) : Int32
- #<=>(other : Int)
- #==(other : BigDecimal) : Bool

  Compares this object to other based on the receiver’s `<=>` method, returning `true` if it returns `0`.

- #ceil : BigDecimal

  Rounds towards positive infinity.

- #clone
- #div(other : BigDecimal, precision = DEFAULT_PRECISION) : BigDecimal

  Divides `self` with another `BigDecimal`, with an optionally configurable precision.

- #div(other : BigDecimal, *, max_div_iterations = DEFAULT_MAX_DIV_ITERATIONS) : BigDecimal

  Divides `self` with another `BigDecimal`, with an optionally configurable precision.

  DEPRECATED Use `#div(other : BigDecimal, precision = DEFAULT_PRECISION)` instead

- #floor : BigDecimal

  Rounds towards negative infinity.

- #hash(hasher)

  Appends this object's value to hasher, and returns the modified hasher.

- #integer? : Bool

  Returns `true` if `self` is an integer.

- #normalize_quotient(other : BigDecimal, quotient : BigInt) : BigInt

  Returns the quotient as absolutely negative if `self` and other have different signs, otherwise returns the quotient.

- #round(digits : Number, base = 10, *, mode : RoundingMode = :ties_even) : BigDecimal

  Rounds this number to a given precision.

- #round_away : BigDecimal

  Rounds towards the nearest integer.

- #round_even : BigDecimal

  Rounds towards the nearest integer.

- #scale : UInt64
- #scale_to(new_scale : BigDecimal) : BigDecimal

  Scales a `BigDecimal` to another `BigDecimal`, so they can be computed easier.

- #to_big_d
- #to_big_f

  Converts to `BigFloat`.

- #to_big_i : BigInt

  Converts to `BigInt`.

- #to_big_r : BigRational
- #to_f : Float64

  Converts to `Float64`.

- #to_f! : Float64

  Converts to `Float64`.

- #to_f32 : Float32

  Converts to `Float32`.

- #to_f32!

  Converts to `Float32`.

- #to_f64 : Float64

  Converts to `Float64`.

- #to_f64! : Float64

  Converts to `Float64`.

- #to_i : Int32

  Converts to `Int32`.

- #to_i! : Int32

  Converts to `Int32`.

- #to_i16 : Int16

  Converts to `Int16`.

- #to_i16!

  Converts to `Int16`.

- #to_i32 : Int32

  Converts to `Int32`.

- #to_i32! : Int32

  Converts to `Int32`.

- #to_i64 : Int64

  Converts to `Int64`.

- #to_i64!

  Converts to `Int64`.

- #to_i8 : Int8

  Converts to `Int8`.

- #to_i8!

  Converts to `Int8`.

- #to_s(io : IO) : Nil

  Prints a nicely readable and concise string representation of this object, typically intended for users, to io.

- #to_u : UInt32

  Converts to `UInt32`.

- #to_u! : UInt32

  Converts to `UInt32`.

- #to_u16 : UInt16

  Converts to `UInt16`.

- #to_u16!

  Converts to `UInt16`.

- #to_u32 : UInt32

  Converts to `UInt32`.

- #to_u32! : UInt32

  Converts to `UInt32`.

- #to_u64 : UInt64

  Converts to `UInt64`.

- #to_u64!

  Converts to `UInt64`.

- #to_u8 : UInt8

  Converts to `UInt8`.

- #to_u8!

  Converts to `UInt8`.

- #trunc : BigDecimal

  Rounds towards zero.

- #value : BigInt
- #zero? : Bool

  Returns `true` if `self` is equal to zero.

### Instance methods inherited from module `Comparable(BigDecimal)`

<(other : T) : Bool <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) : Bool >, >=(other : T) >=, clamp(min, max)
clamp(range : Range) clamp

### Instance methods inherited from module `Comparable(BigRational)`

<(other : T) : Bool <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) : Bool >, >=(other : T) >=, clamp(min, max)
clamp(range : Range) clamp

### Instance methods inherited from module `Comparable(Float)`

<(other : T) : Bool <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) : Bool >, >=(other : T) >=, clamp(min, max)
clamp(range : Range) clamp

### Instance methods inherited from module `Comparable(Int)`

<(other : T) : Bool <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) : Bool >, >=(other : T) >=, clamp(min, max)
clamp(range : Range) clamp

### Instance methods inherited from struct `Number`

*(other : BigFloat) : BigFloat
*(other : Complex) : Complex *, +(other : BigFloat)
+(other : Complex) : Complex
+ +, -(other : BigFloat)
-(other : Complex) : Complex -, /(other : BigFloat) : BigFloat
/(other : Complex) : Complex /, //(other) //, <=>(other) : Int32 | Nil <=>, ==(other : Complex) ==, abs : self abs, abs2 abs2, cis : Complex cis, divmod(number) divmod, format(io : IO, separator = '.', delimiter = ',', decimal_places : Int | Nil = nil, *, group : Int = 3, only_significant : Bool = false) : Nil
format(separator = '.', delimiter = ',', decimal_places : Int | Nil = nil, *, group : Int = 3, only_significant : Bool = false) : String format, humanize(io : IO, precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, prefixes : Indexable = SI_PREFIXES) : Nil
humanize(io : IO, precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, prefixes : Proc) : Nil
humanize(precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, prefixes = SI_PREFIXES) : String
humanize(io : IO, precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, &prefixes : Int32, Float64 -> Tuple(Int32, _) | Tuple(Int32, _, Bool)) : Nil
humanize(precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, &) : String
humanize(precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, prefixes : Proc) : String humanize, i : Complex i, integer? : Bool integer?, negative? : Bool negative?, positive? : Bool positive?, round(mode : RoundingMode = :ties_even) : self
round(digits : Number, base = 10, *, mode : RoundingMode = :ties_even) round, sign : Int32 sign, significant(digits, base = 10) significant, step(*, to limit = nil, exclusive : Bool = false, &) : Nil
step(*, to limit = nil, exclusive : Bool = false) step, to_big_f : BigFloat to_big_f, to_c : Complex to_c, to_yaml(yaml : YAML::Nodes::Builder) : Nil to_yaml, zero? : Bool zero?

### Constructor methods inherited from struct `Number`

additive_identity : self additive_identity, multiplicative_identity : self multiplicative_identity, zero : self zero

### Class methods inherited from struct `Number`

si_prefix(magnitude : Int, prefixes = SI_PREFIXES) : Char | Nil si_prefix

### Macros inherited from struct `Number`

[](*nums) [], slice(*nums, read_only = false) slice, static_array(*nums) static_array

### Instance methods inherited from module `Comparable(BigFloat)`

<(other : T) : Bool <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) : Bool >, >=(other : T) >=, clamp(min, max)
clamp(range : Range) clamp

### Instance methods inherited from module `Steppable`

step(*, to limit = nil, by step, exclusive : Bool = false, &) : Nil
step(*, to limit = nil, by step, exclusive : Bool = false) step

### Instance methods inherited from module `Comparable(Number)`

<(other : T) : Bool <, <=(other : T) <=, <=>(other : T) <=>, ==(other : T) ==, >(other : T) : Bool >, >=(other : T) >=, clamp(min, max)
clamp(range : Range) clamp

### Instance methods inherited from struct `Value`

==(other : JSON::Any)
==(other : YAML::Any)
==(other) ==, dup dup

### Instance methods inherited from class `Object`

! : Bool !, !=(other) !=, !~(other) !~, ==(other) ==, ===(other : JSON::Any)
===(other : YAML::Any)
===(other) ===, =~(other) =~, as(type : Class) as, as?(type : Class) as?, class class, dup dup, hash(hasher)
hash hash, in?(collection : Object) : Bool
in?(*values : Object) : Bool in?, inspect(io : IO) : Nil
inspect : String inspect, is_a?(type : Class) : Bool is_a?, itself itself, nil? : Bool nil?, not_nil!(message)
not_nil! not_nil!, pretty_inspect(width = 79, newline = "\n", indent = 0) : String pretty_inspect, pretty_print(pp : PrettyPrint) : Nil pretty_print, responds_to?(name : Symbol) : Bool responds_to?, tap(&) tap, to_json(io : IO) : Nil
to_json : String to_json, to_pretty_json(indent : String = " ") : String
to_pretty_json(io : IO, indent : String = " ") : Nil to_pretty_json, to_s(io : IO) : Nil
to_s : String to_s, to_yaml(io : IO) : Nil
to_yaml : String to_yaml, try(&) try, unsafe_as(type : T.class) forall T unsafe_as

### Class methods inherited from class `Object`

from_json(string_or_io, root : String)
from_json(string_or_io) from_json, from_yaml(string_or_io : String | IO) from_yaml

### Macros inherited from class `Object`

class_getter(*names, &block) class_getter, class_getter!(*names) class_getter!, class_getter?(*names, &block) class_getter?, class_property(*names, &block) class_property, class_property!(*names) class_property!, class_property?(*names, &block) class_property?, class_setter(*names) class_setter, def_clone def_clone, def_equals(*fields) def_equals, def_equals_and_hash(*fields) def_equals_and_hash, def_hash(*fields) def_hash, delegate(*methods, to object) delegate, forward_missing_to(delegate) forward_missing_to, getter(*names, &block) getter, getter!(*names) getter!, getter?(*names, &block) getter?, property(*names, &block) property, property!(*names) property!, property?(*names, &block) property?, setter(*names) setter

##
Constructor Detail

def self.new(value : BigInt, scale : UInt64) #

Creates a new `BigDecimal` from `BigInt` value and `UInt64` scale, which matches the internal representation.

def self.new(num : Float) #

Creates a new `BigDecimal` from `Float`.

NOTE Floats are fundamentally less precise than BigDecimals, which makes initialization from them risky.

def self.new(num : BigRational) #

Creates a new `BigDecimal` from `BigRational`.

NOTE BigRational are fundamentally more precise than BigDecimals, which makes initialization from them risky.

def self.new(num : BigDecimal) #

Returns num. Useful for generic code that does `T.new(...)` with `T` being a `Number`.

def self.new(num : Int = 0, scale : Int = 0) #

Creates a new `BigDecimal` from `Int`.

def self.new(str : String) #

Creates a new `BigDecimal` from a `String`.

Allows only valid number strings with an optional negative sign.

##
Instance Method Detail

def %(other : BigDecimal) : BigDecimal #
def %(other : Int) #
def *(other : BigDecimal) : BigDecimal #
def *(other : Number) : BigDecimal #
def **(other : Int) : BigDecimal #

Raises the decimal to the otherth power

    require "big"

    BigDecimal.new(1234, 2) ** 2 # => 152.2756

def +(other : BigDecimal) : BigDecimal #
def +(other : Number) : BigDecimal #
def -(other : BigDecimal) : BigDecimal #
def -(other : Number) : BigDecimal #
def - : BigDecimal #
def /(other : BigDecimal) : BigDecimal #
def /(other : BigInt) : BigDecimal #
def /(other : BigFloat) : BigDecimal #
def /(other : BigRational) : BigRational #
def /(other : Int8) : BigDecimal #
def /(other : UInt8) : BigDecimal #
def /(other : Int16) : BigDecimal #
def /(other : UInt16) : BigDecimal #
def /(other : Int32) : BigDecimal #
def /(other : UInt32) : BigDecimal #
def /(other : Int64) : BigDecimal #
def /(other : UInt64) : BigDecimal #
def /(other : Int128) : BigDecimal #
def /(other : UInt128) : BigDecimal #
def /(other : Float32) : BigDecimal #
def /(other : Float64) : BigDecimal #
def <=>(other : BigDecimal) : Int32 #
Description copied from module Comparable(BigDecimal)

The comparison operator. Returns `0` if the two objects are equal, a negative number if this object is considered less than other, a positive number if this object is considered greater than other, or `nil` if the two objects are not comparable.

Subclasses define this method to provide class-specific ordering.

The comparison operator is usually used to sort values:

    # Sort in a descending way:
    [3, 1, 2].sort { |x, y| y <=> x } # => [3, 2, 1]

    # Sort in an ascending way:
    [3, 1, 2].sort { |x, y| x <=> y } # => [1, 2, 3]

def <=>(other : BigRational) : Int32 #
def <=>(other : Float::Primitive) : Int32 | Nil #
def <=>(other : BigFloat) : Int32 #
def <=>(other : Int) #
def ==(other : BigDecimal) : Bool #
Description copied from module Comparable(BigDecimal)

Compares this object to other based on the receiver’s `<=>` method, returning `true` if it returns `0`.

Also returns `true` if this and other are the same object.

def ceil : BigDecimal #

Rounds towards positive infinity.

def clone #
def div(other : BigDecimal, precision = DEFAULT_PRECISION) : BigDecimal #

Divides `self` with another `BigDecimal`, with an optionally configurable precision.

When the division is inexact, the returned value rounds towards negative infinity, and its scale is never greater than `scale - other.scale + precision`.

    BigDecimal.new(1).div(BigDecimal.new(2))    # => BigDecimal(@value=5, @scale=2)
    BigDecimal.new(1).div(BigDecimal.new(3), 5) # => BigDecimal(@value=33333, @scale=5)

def div(other : BigDecimal, *, max_div_iterations = DEFAULT_MAX_DIV_ITERATIONS) : BigDecimal #

Divides `self` with another `BigDecimal`, with an optionally configurable precision.

When the division is inexact, the returned value rounds towards negative infinity, and its scale is never greater than `scale - other.scale + precision`.

    BigDecimal.new(1).div(BigDecimal.new(2))    # => BigDecimal(@value=5, @scale=2)
    BigDecimal.new(1).div(BigDecimal.new(3), 5) # => BigDecimal(@value=33333, @scale=5)

DEPRECATED Use `#div(other : BigDecimal, precision = DEFAULT_PRECISION)` instead

def floor : BigDecimal #

Rounds towards negative infinity.

def hash(hasher) #
Description copied from class Object

Appends this object's value to hasher, and returns the modified hasher.

Usually the macro `def_hash` can be used to generate this method. Otherwise, invoke `#hash(hasher)` on each object's instance variables to accumulate the result:

    def hash(hasher)
      hasher = @some_ivar.hash(hasher)
      hasher = @some_other_ivar.hash(hasher)
      hasher
    end

def integer? : Bool #

Returns `true` if `self` is an integer.

Non-integer types may return `true` as long as `self` denotes a finite value without any fractional parts.

    1.integer?       # => true
    1.0.integer?     # => true
    1.2.integer?     # => false
    (1 / 0).integer? # => false
    (0 / 0).integer? # => false

def normalize_quotient(other : BigDecimal, quotient : BigInt) : BigInt #

Returns the quotient as absolutely negative if `self` and other have different signs, otherwise returns the quotient.

def round(digits : Number, base = 10, *, mode : RoundingMode = :ties_even) : BigDecimal #
Description copied from struct Number

Rounds this number to a given precision.

Rounds to the specified number of digits after the decimal place, (or before if negative), in base base.

The rounding mode controls the direction of the rounding. The default is `RoundingMode::TIES_EVEN` which rounds to the nearest integer, with ties (fractional value of `0.5`) being rounded to the even neighbor (Banker's rounding).

    -1763.116.round(2) # => -1763.12

def round_away : BigDecimal #

Rounds towards the nearest integer. If both neighboring integers are equidistant, rounds away from zero.

def round_even : BigDecimal #

Rounds towards the nearest integer. If both neighboring integers are equidistant, rounds towards the even neighbor (Banker's rounding).

def scale : UInt64 #
def scale_to(new_scale : BigDecimal) : BigDecimal #

Scales a `BigDecimal` to another `BigDecimal`, so they can be computed easier.

def to_big_d #
def to_big_f #

Converts to `BigFloat`.

def to_big_i : BigInt #

Converts to `BigInt`. Truncates anything on the right side of the decimal point.

def to_big_r : BigRational #
def to_f : Float64 #

Converts to `Float64`. Raises `OverflowError` in case of overflow.

def to_f! : Float64 #

Converts to `Float64`. In case of overflow a wrapping is performed.

def to_f32 : Float32 #

Converts to `Float32`. Raises `OverflowError` in case of overflow.

def to_f32! #

Converts to `Float32`. In case of overflow a wrapping is performed.

def to_f64 : Float64 #

Converts to `Float64`. Raises `OverflowError` in case of overflow.

def to_f64! : Float64 #

Converts to `Float64`. In case of overflow a wrapping is performed.

def to_i : Int32 #

Converts to `Int32`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_i! : Int32 #

Converts to `Int32`. Truncates anything on the right side of the decimal point. In case of overflow a wrapping is performed.

def to_i16 : Int16 #

Converts to `Int16`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_i16! #

Converts to `Int16`. Truncates anything on the right side of the decimal point. In case of overflow a wrapping is performed.

def to_i32 : Int32 #

Converts to `Int32`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_i32! : Int32 #

Converts to `Int32`. Truncates anything on the right side of the decimal point. In case of overflow a wrapping is performed.

def to_i64 : Int64 #

Converts to `Int64`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_i64! #

Converts to `Int64`. Truncates anything on the right side of the decimal point. In case of overflow a wrapping is performed.

def to_i8 : Int8 #

Converts to `Int8`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_i8! #

Converts to `Int8`. Truncates anything on the right side of the decimal point. In case of overflow a wrapping is performed.

def to_s(io : IO) : Nil #
Description copied from class Object

Prints a nicely readable and concise string representation of this object, typically intended for users, to io.

This method is called when an object is interpolated in a string literal:

    "foo #{bar} baz" # calls bar.to_io with the builder for this string

`IO#<<` calls this method to append an object to itself:

    io << bar # calls bar.to_s(io)

Thus implementations must not interpolate `self` in a string literal or call `io << self` which both would lead to an endless loop.

Also see `#inspect(IO)`.

def to_u : UInt32 #

Converts to `UInt32`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_u! : UInt32 #

Converts to `UInt32`. Truncates anything on the right side of the decimal point, converting negative to positive. In case of overflow a wrapping is performed.

def to_u16 : UInt16 #

Converts to `UInt16`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_u16! #

Converts to `UInt16`. Truncates anything on the right side of the decimal point, converting negative to positive. In case of overflow a wrapping is performed.

def to_u32 : UInt32 #

Converts to `UInt32`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_u32! : UInt32 #

Converts to `UInt32`. Truncates anything on the right side of the decimal point, converting negative to positive. In case of overflow a wrapping is performed.

def to_u64 : UInt64 #

Converts to `UInt64`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_u64! #

Converts to `UInt64`. Truncates anything on the right side of the decimal point, converting negative to positive. In case of overflow a wrapping is performed.

def to_u8 : UInt8 #

Converts to `UInt8`. Truncates anything on the right side of the decimal point. Raises `OverflowError` in case of overflow.

def to_u8! #

Converts to `UInt8`. Truncates anything on the right side of the decimal point, converting negative to positive. In case of overflow a wrapping is performed.

def trunc : BigDecimal #

Rounds towards zero.

def value : BigInt #
def zero? : Bool #
Description copied from struct Number

Returns `true` if `self` is equal to zero.

    0.zero? # => true
    5.zero? # => false