Class: Abachrome::AbcDecimal

Inherits:
Object
  • Object
show all
Extended by:
Forwardable
Defined in:
lib/abachrome/abc_decimal.rb

Constant Summary collapse

DEFAULT_PRECISION =
(ENV["ABC_DECIMAL_PRECISION"] || "24").to_i

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(value, precision = DEFAULT_PRECISION) ⇒ AbcDecimal

Initializes a new AbcDecimal object with the specified value and precision.

If an AbcDecimal is provided, its internal value is used. If a BigDecimal or Rational is provided, it’s used directly. Otherwise, the value is converted to a string and parsed as a BigDecimal. Defaults to DEFAULT_PRECISION.

Parameters:

  • value (AbcDecimal, BigDecimal, Rational, #to_s)

    The numeric value to represent.

  • precision (Integer) (defaults to: DEFAULT_PRECISION)

    The decimal precision to use (number of significant digits).



37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/abachrome/abc_decimal.rb', line 37

def initialize(value, precision = DEFAULT_PRECISION)
  @precision = precision
  @value = case value
           when AbcDecimal
             value.value
           when BigDecimal
             value
           when Rational
             value
           else
             BigDecimal(value.to_s, precision)
           end
end

Instance Attribute Details

#precisionObject

Returns the value of attribute precision.



24
25
26
# File 'lib/abachrome/abc_decimal.rb', line 24

def precision
  @precision
end

#valueObject

Returns the value of attribute value.



24
25
26
# File 'lib/abachrome/abc_decimal.rb', line 24

def value
  @value
end

Class Method Details

.atan2(y, x) ⇒ AbcDecimal

Calculates the arctangent of y/x using the signs of the arguments to determine the quadrant. Unlike the standard Math.atan2, this method accepts AbcDecimal objects or any values that can be converted to AbcDecimal.

Parameters:

Returns:

  • (AbcDecimal)

    The angle in radians between the positive x-axis and the ray to the point (x,y)



327
328
329
330
331
# File 'lib/abachrome/abc_decimal.rb', line 327

def self.atan2(y, x)
  y_value = y.is_a?(AbcDecimal) ? y.value : AbcDecimal(y).value
  x_value = x.is_a?(AbcDecimal) ? x.value : AbcDecimal(x).value
  new(Math.atan2(y_value, x_value))
end

.from_float(float, precision = DEFAULT_PRECISION) ⇒ AbcDecimal

Creates a new AbcDecimal instance from a float value.

Parameters:

  • float (Float)

    The floating point number to convert to an AbcDecimal

  • precision (Integer) (defaults to: DEFAULT_PRECISION)

    The precision to use for the decimal representation (default: DEFAULT_PRECISION)

Returns:

  • (AbcDecimal)

    A new AbcDecimal instance representing the given float value



96
97
98
# File 'lib/abachrome/abc_decimal.rb', line 96

def self.from_float(float, precision = DEFAULT_PRECISION)
  new(float, precision)
end

.from_integer(integer, precision = DEFAULT_PRECISION) ⇒ AbcDecimal

Creates a new AbcDecimal from an integer value.

Parameters:

  • integer (Integer)

    The integer value to convert to an AbcDecimal

  • precision (Integer) (defaults to: DEFAULT_PRECISION)

    The precision to use for the decimal, defaults to DEFAULT_PRECISION

Returns:

  • (AbcDecimal)

    A new AbcDecimal instance with the specified integer value and precision



105
106
107
# File 'lib/abachrome/abc_decimal.rb', line 105

def self.from_integer(integer, precision = DEFAULT_PRECISION)
  new(integer, precision)
end

.from_rational(rational, precision = DEFAULT_PRECISION) ⇒ AbcDecimal

Creates a new AbcDecimal from a Rational number.

Parameters:

  • rational (Rational)

    The rational number to convert to an AbcDecimal

  • precision (Integer) (defaults to: DEFAULT_PRECISION)

    The precision to use for the decimal representation, defaults to DEFAULT_PRECISION

Returns:

  • (AbcDecimal)

    A new AbcDecimal instance with the value of the given rational number



87
88
89
# File 'lib/abachrome/abc_decimal.rb', line 87

def self.from_rational(rational, precision = DEFAULT_PRECISION)
  new(rational, precision)
end

.from_string(str, precision = DEFAULT_PRECISION) ⇒ AbcDecimal

Creates a new AbcDecimal from a string representation of a number.

Parameters:

  • str (String)

    The string representation of a number to convert to an AbcDecimal

  • precision (Integer) (defaults to: DEFAULT_PRECISION)

    The precision to use for the decimal value (number of significant digits after the decimal point). Defaults to DEFAULT_PRECISION

Returns:

  • (AbcDecimal)

    A new AbcDecimal instance initialized with the given string value and precision



78
79
80
# File 'lib/abachrome/abc_decimal.rb', line 78

def self.from_string(str, precision = DEFAULT_PRECISION)
  new(str, precision)
end

Instance Method Details

#%(other) ⇒ AbcDecimal

Performs modulo operation with another value.

Parameters:

  • other (Numeric, AbcDecimal)

    The divisor for the modulo operation

Returns:

  • (AbcDecimal)

    A new AbcDecimal containing the remainder after division



163
164
165
166
# File 'lib/abachrome/abc_decimal.rb', line 163

def %(other)
  other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
  self.class.new(@value % other_value)
end

#*(other) ⇒ AbcDecimal

Multiplies this AbcDecimal by another value.

dec1 = AbcDecimal.new(5) dec2 = AbcDecimal.new(2) result = dec1 * dec2 # => AbcDecimal representing 10

# With a non-AbcDecimal value result = dec1 * 3 # => AbcDecimal representing 15

Parameters:

  • other (Object)

    The value to multiply by. If not an AbcDecimal, it will be converted to one.

Returns:

  • (AbcDecimal)

    A new AbcDecimal instance representing the product of this decimal and the other value.



141
142
143
144
# File 'lib/abachrome/abc_decimal.rb', line 141

def *(other)
  other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
  self.class.new(@value * other_value)
end

#**(other) ⇒ AbcDecimal

Raises self to the power of another value. This method handles different input types, including Rational values and other AbcDecimal instances.

Parameters:

  • other (Numeric, Rational, AbcDecimal)

    The exponent to raise this value to

Returns:

  • (AbcDecimal)

    A new AbcDecimal representing self raised to the power of other



187
188
189
190
191
192
193
194
# File 'lib/abachrome/abc_decimal.rb', line 187

def **(other)
  if other.is_a?(Rational)
    self.class.new(@value**other)
  else
    other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
    self.class.new(@value**other_value)
  end
end

#+(other) ⇒ Object

# Addition operation # # Adds another value to this decimal. # # @param other [AbcDecimal, Numeric] The value to add. If not an AbcDecimal, # it will be converted to one. # @return [AbcDecimal] A new AbcDecimal instance with the sum of the two values



116
117
118
119
# File 'lib/abachrome/abc_decimal.rb', line 116

def +(other)
  other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
  self.class.new(@value + other_value)
end

#-(other) ⇒ AbcDecimal

Subtracts another numeric value from this AbcDecimal.

Parameters:

  • other (AbcDecimal, Numeric)

    The value to subtract from this AbcDecimal.

Returns:

  • (AbcDecimal)

    A new AbcDecimal representing the result of the subtraction.



125
126
127
128
# File 'lib/abachrome/abc_decimal.rb', line 125

def -(other)
  other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
  self.class.new(@value - other_value)
end

#/(other) ⇒ AbcDecimal

Divides this decimal by another value.

decimal = AbcDecimal.new(10) result = decimal / 2 # => AbcDecimal.new(5)

Parameters:

  • other (Numeric, AbcDecimal)

    The divisor, which can be an AbcDecimal instance or any numeric value

Returns:

  • (AbcDecimal)

    A new AbcDecimal representing the result of the division



154
155
156
157
# File 'lib/abachrome/abc_decimal.rb', line 154

def /(other)
  other_value = other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value
  self.class.new(@value / other_value)
end

#<(other) ⇒ Boolean

Compares this decimal with another value.

dec1 = AbcDecimal.new(1.5) dec2 = AbcDecimal.new(2.0) dec1 < dec2 #=> true dec1 < 2.0 #=> true

Parameters:

  • other (Object)

    The value to compare with. Will be coerced to AbcDecimal if not already an instance.

Returns:

  • (Boolean)

    true if this decimal is less than the other value, false otherwise.



264
265
266
# File 'lib/abachrome/abc_decimal.rb', line 264

def <(other)
  @value < (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
end

#<=(other) ⇒ Boolean

Compares this AbcDecimal with another value.

it will be converted to one. false otherwise.

Parameters:

  • other (AbcDecimal, Numeric)

    The value to compare with. If not an AbcDecimal,

Returns:

  • (Boolean)

    true if this AbcDecimal is less than or equal to the other value,



274
275
276
# File 'lib/abachrome/abc_decimal.rb', line 274

def <=(other)
  @value <= (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
end

#<=>(other) ⇒ Integer?

Compares this AbcDecimal instance with another AbcDecimal or a value that can be converted to an AbcDecimal.

If not an AbcDecimal, it will be converted using AbcDecimal(). 0 if they are equal, 1 if self is greater than other, or nil if the comparison is not possible.

Parameters:

  • other (Object)

    The value to compare with this AbcDecimal.

Returns:

  • (Integer, nil)

    Returns -1 if self is less than other,



232
233
234
# File 'lib/abachrome/abc_decimal.rb', line 232

def <=>(other)
  @value <=> (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
end

#==(other) ⇒ Boolean

Compares this decimal value with another value for equality. Attempts to convert the other value to an AbcDecimal if it isn’t one already.

Parameters:

  • other (Object)

    The value to compare against this AbcDecimal

Returns:

  • (Boolean)

    True if the values are equal, false otherwise



219
220
221
# File 'lib/abachrome/abc_decimal.rb', line 219

def ==(other)
  @value == (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
end

#>(other) ⇒ Boolean

Compares this decimal with another value.

convertible to AbcDecimal

Parameters:

  • other (Object)

    The value to compare with. Can be an AbcDecimal or any value

Returns:

  • (Boolean)

    true if this decimal is greater than the other value, false otherwise



241
242
243
# File 'lib/abachrome/abc_decimal.rb', line 241

def >(other)
  @value > (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
end

#>=(other) ⇒ Boolean

Compares this decimal value with another value.

it will be converted to one. false otherwise.

Parameters:

  • other (Object)

    The value to compare against. If not an AbcDecimal,

Returns:

  • (Boolean)

    true if this decimal is greater than or equal to the other value,



251
252
253
# File 'lib/abachrome/abc_decimal.rb', line 251

def >=(other)
  @value >= (other.is_a?(AbcDecimal) ? other.value : AbcDecimal(other).value)
end

#abs(*args) ⇒ AbcDecimal

Returns the absolute value (magnitude) of the decimal number.

Wraps BigDecimal#abs to ensure return values are properly converted to AbcDecimal.

Parameters:

  • args (Array)

    Optional arguments to pass to BigDecimal#abs

Returns:

  • (AbcDecimal)

    The absolute value of the decimal number



300
301
302
# File 'lib/abachrome/abc_decimal.rb', line 300

def abs(*args)
  AbcDecimal(@value.abs(*args))
end

#clamp(min, max) ⇒ AbcDecimal

Constrains the value to be between the specified minimum and maximum values.

AbcDecimal(5).clamp(0, 10) # => 5 AbcDecimal(15).clamp(0, 10) # => 10 AbcDecimal(-5).clamp(0, 10) # => 0

Parameters:

  • min (Numeric, AbcDecimal)

    The minimum value to clamp to

  • max (Numeric, AbcDecimal)

    The maximum value to clamp to

Returns:

  • (AbcDecimal)

    A new AbcDecimal within the specified range



177
178
179
# File 'lib/abachrome/abc_decimal.rb', line 177

def clamp(min,max)
  @value.clamp(AbcDecimal(min),AbcDecimal(max))
end

#coerce(other) ⇒ Array<AbcDecimal>

Allows for mixed arithmetic operations between AbcDecimal and other numeric types.

allowing Ruby to perform arithmetic operations with mixed types

Parameters:

  • other (Numeric)

    The other number to be coerced into an AbcDecimal object

Returns:

  • (Array<AbcDecimal>)

    A two-element array containing the coerced value and self,



201
202
203
# File 'lib/abachrome/abc_decimal.rb', line 201

def coerce(other)
  [self.class.new(other), self]
end

#inspectString

Returns a string representation of the decimal value for inspection purposes. This method returns a formatted string that includes the class name and the string representation of the decimal value itself.

Returns:

  • (String)

    A string in the format “ClassName(‘value’)”



210
211
212
# File 'lib/abachrome/abc_decimal.rb', line 210

def inspect
  "#{self.class}('#{self}')"
end

#negative?Boolean

Returns true if the internal value is negative, false otherwise.

Returns:

  • (Boolean)

    true if the value is negative, false otherwise



316
317
318
# File 'lib/abachrome/abc_decimal.rb', line 316

def negative?
  @value.negative?
end

#round(*args) ⇒ AbcDecimal

Rounds this decimal to a specified precision.

the number of decimal places to round to and the rounding mode. decimal = AbcDecimal(3.14159) decimal.round(2) #=> 3.14 decimal = AbcDecimal(3.5) decimal.round(0, half: :up) #=> 4

Examples:

Round to 2 decimal places


Round with specific rounding mode


Parameters:

  • args (Array)

    Arguments to be passed to BigDecimal#round. Can include

Returns:

  • (AbcDecimal)

    A new AbcDecimal instance with the rounded value



290
291
292
# File 'lib/abachrome/abc_decimal.rb', line 290

def round(*args)
  AbcDecimal(@value.round(*args))
end

#sqrtAbcDecimal

Returns the square root of the AbcDecimal value. Calculates the square root by using Ruby’s built-in Math.sqrt function and converting the result back to an AbcDecimal.

Returns:

  • (AbcDecimal)

    A new AbcDecimal representing the square root of the value



309
310
311
# File 'lib/abachrome/abc_decimal.rb', line 309

def sqrt
  AbcDecimal(Math.sqrt(@value))
end

#to_fFloat

Converts the decimal value to a floating-point number.

Returns:

  • (Float)

    the floating-point representation of the AbcDecimal value



69
70
71
# File 'lib/abachrome/abc_decimal.rb', line 69

def to_f
  @value.to_f
end

#to_sString

Returns a string representation of the decimal value.

This method converts the internal value to a String, using a fixed-point notation format. If the internal value is a Rational, it’s first converted to a BigDecimal with the configured precision before string conversion.

Returns:

  • (String)

    The decimal value as a string in fixed-point notation



58
59
60
61
62
63
64
# File 'lib/abachrome/abc_decimal.rb', line 58

def to_s
  if @value.is_a?(Rational)
    BigDecimal(@value, precision).to_s("F")
  else
    @value.to_s("F") # different behaviour than default BigDecimal
  end
end