struct BigDecimal

Overview

ABigDecimal can represent arbitrarily large precision decimals.

It is internally represented by a pair ofBigInt andUInt64: value and scale. Value contains the actual value, and scale tells the decimal point place. E.g. when value is1234 and scale2, the result is12.34.

NOTE To useBigDecimal, you must explicitly import it withrequire "big"

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

Included Modules

Defined in:

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

Constant Summary

DEFAULT_MAX_DIV_ITERATIONS = 100_u64

DEPRECATED UseDEFAULT_PRECISION instead

DEFAULT_PRECISION = 100_u64

Constructors

Class Method Summary

Instance Method Summary

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
, hash(hasher) hash, humanize(io : IO, precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, unit_separator = nil, prefixes : Indexable = SI_PREFIXES) : Nil
humanize(io : IO, precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, unit_separator = nil, prefixes : Proc) : Nil
humanize(precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, unit_separator = nil, prefixes = SI_PREFIXES) : String
humanize(io : IO, precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, unit_separator = nil, &prefixes : Int32, Float64 -> Tuple(Int32, _) | Tuple(Int32, _, Bool)) : Nil
humanize(precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, unit_separator = nil, &) : String
humanize(precision = 3, separator = '.', delimiter = ',', *, base = 10 ** 3, significant = true, unit_separator = nil, 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 : Log::Metadata::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 : String | IO, root : String)
from_json(string_or_io : String | 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 newBigDecimal fromBigIntvalue andUInt64scale, which matches the internal representation.


def self.new(ctx : YAML::ParseContext, node : YAML::Nodes::Node) : self #

def self.new(num : Float) : self #

Creates a newBigDecimal fromFloat.

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


def self.new(num : BigRational) : self #

Creates a newBigDecimal fromBigRational.

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


def self.new(num : BigDecimal) : self #

Returnsnum. Useful for generic code that doesT.new(...) withT being aNumber.


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

Creates a newBigDecimal fromInt.


def self.new(str : String) #

Creates a newBigDecimal from aString.

Allows only valid number strings with an optional negative sign.


def self.new(pull : JSON::PullParser) : self #

Class Method Detail

def self.from_json_object_key?(key : String) : BigDecimal | Nil #

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 theotherth 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. Returns0 if the two objects are equal, a negative number if this object is considered less thanother, a positive number if this object is considered greater thanother, ornil 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) : Int32 #

def ==(other : BigDecimal) : Bool #
Description copied from module Comparable(BigDecimal)

Compares this object toother based on the receiver’s<=> method, returningtrue if it returns0.

Also returnstrue if this andother are the same object.


def ceil : BigDecimal #

Rounds towards positive infinity.


def clone #

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

Dividesself with anotherBigDecimal, 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 #

Dividesself with anotherBigDecimal, 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 format(io : IO, separator = '.', delimiter = ',', decimal_places : Int | Nil = nil, *, group : Int = 3, only_significant : Bool = false) : Nil #

Prints this number as aString using a customizable format.

separator is used as decimal separator,delimiter as thousands delimiter between batches ofgroup digits.

Ifdecimal_places isnil, all significant decimal places are printed (similar to#to_s). If the argument has a numeric value, the number of visible decimal places will be fixed to that amount.

Trailing zeros are omitted ifonly_significant istrue.

123_456.789.format                                            # => "123,456.789"
123_456.789.format(',', '.')                                  # => "123.456,789"
123_456.789.format(decimal_places: 2)                         # => "123,456.79"
123_456.789.format(decimal_places: 6)                         # => "123,456.789000"
123_456.789.format(decimal_places: 6, only_significant: true) # => "123,456.789"

def integer? : Bool #

Returnstrue ifself is an integer.

Non-integer types may returntrue as long asself 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 thequotient as absolutely negative ifself andother have different signs, otherwise returns thequotient.


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 ofdigits after the decimal place, (or before if negative), in basebase.

The roundingmode controls the direction of the rounding. The default is RoundingMode::TIES_EVEN which rounds to the nearest integer, with ties (fractional value of0.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 aBigDecimal to anotherBigDecimal, so they can be computed easier.


def to_big_d #

def to_big_f #

Converts toBigFloat.


def to_big_i : BigInt #

Converts toBigInt. Truncates anything on the right side of the decimal point.


def to_big_r : BigRational #

def to_f : Float64 #

Converts toFloat64. RaisesOverflowError in case of overflow.


def to_f! : Float64 #

Converts toFloat64. In case of overflow a wrapping is performed.


def to_f32 : Float32 #

Converts toFloat32. RaisesOverflowError in case of overflow.


def to_f32! #

Converts toFloat32. In case of overflow a wrapping is performed.


def to_f64 : Float64 #

Converts toFloat64. RaisesOverflowError in case of overflow.


def to_f64! : Float64 #

Converts toFloat64. In case of overflow a wrapping is performed.


def to_i : Int32 #

Converts toInt32. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_i! : Int32 #

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


def to_i16 : Int16 #

Converts toInt16. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_i16! #

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


def to_i32 : Int32 #

Converts toInt32. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_i32! : Int32 #

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


def to_i64 : Int64 #

Converts toInt64. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_i64! #

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


def to_i8 : Int8 #

Converts toInt8. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_i8! #

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


def to_json(json : JSON::Builder) : Nil #

def to_json_object_key #

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, toio.

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 interpolateself 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 toUInt32. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_u! : UInt32 #

Converts toUInt32. 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 toUInt16. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_u16! #

Converts toUInt16. 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 toUInt32. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_u32! : UInt32 #

Converts toUInt32. 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 toUInt64. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_u64! #

Converts toUInt64. 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 toUInt8. Truncates anything on the right side of the decimal point. RaisesOverflowError in case of overflow.


def to_u8! #

Converts toUInt8. 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

Returnstrue ifself is equal to zero.

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