Ruby-NumRepr

Number representations: Conversion from and to strings for Integer, Float, and BigDecimal classes.

Classes for monetary und percent values.

Installation

sudo gem install numrepr

Usage

Parsing and formatting integers:

require "numrepr/format"

i = NumRepr::Parser.into_i "12.345"
"#{NumRepr::Format.from_i i}"   #=> "12345"

Custom format:

require "numrepr/format"

class MyFmt < NumRepr::Format
  NUMDIGITS = 0       # leave empty if zero
  GRP       = true
  WIDTH     = 8
end

[ 12345, -12345, 0].map { |i| "#{MyFmt.from_i i}" }
#=> ["  12,345", " -12,345", "        "]

The standard parser recognizes comma as decimal separator as well as the dot. You may define a custom parser that demands either.

require "numrepr/format"

%w(12,345 12.345).map { |s| NumRepr::Parser.into_i s }
#=> [12345, 12345]

class ParseDot < NumRepr::Parser
  GRP = "."
end
class ParseComma < NumRepr::Parser
  GRP = ","
end

%w(12,345 12.345).map { |s| ParseDot.into_i s   rescue nil }
#=> [nil, 12345]
%w(12,345 12.345).map { |s| ParseComma.into_i s rescue nil }
#=> [12345, nil]

Parsing and formatting floats respectively decimals:

require "numrepr/format"
require "bigdecimal/util"

class FormatCustom < NumRepr::Format
  # Change these and see what happens:
  NUMDIGITS = 10
  POS       = false
  GRP       = true
  WIDTH     = 16
  DEC       = true    # force decimal point
  NUMPLACES = 0
  RWIDTH    = 8
  ZSIGN     = true
end

nums = %w(
  1.0 0.0 -0.0
  0.1 0.1234 0.00456 0.000456 0.0000456
  123456789.0 1230000.0
  -1234.56789
  NaN Infinity -Infinity
)

nums.each { |s|
  puts "|#{FormatCustom::from_d s.to_d}|"
}

Result:

|   0,000,000,001.        |
|   0,000,000,000.        |
|  -0,000,000,000.        |
|   0,000,000,000.1       |
|   0,000,000,000.123,4   |
|   0,000,000,000.004,56  |
|   0,000,000,000.000,456 |
|   0,000,000,000.000,045,6|
|   0,123,456,789.        |
|   0,001,230,000.        |
|  -0,000,001,234.567,89  |
|             NaN         |
|             Inf         |
|            -Inf         |

Parsing:

require "numrepr/format"
require "bigdecimal/util"

%w(12,345.678,999 12.345,678.999).map { |s| NumRepr::Parser.into_d s }
#=> [12345.678999, 12345.678999]

class ParseDot < NumRepr::Parser
  GRP = "."
end

%w(12,345.678,999 12.345,678.999).map { |s| ParseDot.into_d s rescue nil }
#=> [nil, 12345.678999]

Monetary values

require "numrepr/money"
include NumRepr

class FormatEU < Format
  CHDEC  = ","
  GRP    = true
  CHGRP  = "."
  DASH   = true
  CURSYM = ""
end

amount = Parser.into_money "€  12,345.-"
puts amount
puts "|#{FormatEU::from_money amount}|"

Result:

$12345.00
|€12.345,- |

Default parsing:

require "numrepr/money"
include NumRepr

Parser.into_money "€  12,345.-"    #=> $12345.00
Parser.into_money "€  12.345,-"    #=> $12345.00
Parser.into_money "12.345,-€"      #=> $12345.00
Parser.into_money "EUR  12.345,-"  #=> $12345.00
Parser.into_money "12.345,-EUR"    #=> $12345.00
Parser.into_money "12.345,67 EUR"  #=> $12345.67
Parser.into_money "12.345,67€"     #=> $12345.67

Percent values

require "numrepr/money"
require "numrepr/percent"
include NumRepr

vat = "19%".to_percent
n = "100.00".to_money

n * vat       #=>  $19.00
vat.over n    #=> $119.00
vat.split n   #=> [$84.03, $15.97]

If an amount cannot be split into a base and a percent increase, it can be forced to the next lower number.

require "numrepr/money"
require "numrepr/percent"
include NumRepr

vat = "19%".to_percent
b = "69.99".to_money
vat.split b             #=>  raises NoSolutionError
n, t = vat.split! b     #=> [$58.82, $11.17]
c = vat.over n          #=> $70.00
vat.split c             #=> [$58.82, $11.18]
* (C) 2026 Bertram Scharpf <software@bertram-scharpf.de>.
* License: [BSD-2-Clause+](./LICENSE)
* Repository: [ruby-numrepr](https://github.com/BertramScharpf/ruby-numrepr)