Module:...::Number(3)

๐Ÿ“ฆ version 1.1.3, in alpine 3.24

๐Ÿ’… Module::Generic::Number(3) โ€” the number-wrangling baddie of a class ๐Ÿ’…

okay bestie, so the manual name is Module:...::Number(3) and it's a User Contributed Perl Documentation page, which basically means somebody in the Perl community said "fine, I'll do it myself" and honestly? iconic of them. ๐Ÿซถ

This is part 1 of 3, so don't go anywhere โ€” we're just getting started.


โœจ NAME โœจ

Module::Generic::Number โ€” Number Manipulation Object Class. yes. that's the whole name. it's giving "my functions are my personality" and we're obsessed. ๐ŸŽ€


๐ŸŒธ SYNOPSIS ๐ŸŒธ

okay so here's the whole vibe, verbatim, don't skip it, there's SO much in here:

my $n = Module::Generic::Number->new(10);
# or
my $n = Module::Generic::Number->new( 10,
{
    thousand => ',',
    decimal => '.',
    precision => 2,
    # Currency symbol
    symbol => 'โ‚ฌ',
    # Display currency symbol before or after the number
    precede => 1,
});
# Even accepts numbers in Japanese double bytes
# Will be converted automatically to regular digits.
my $n = Moule::Generic::Number->new( "โˆ’๏ผ‘๏ผ’๏ผ“๏ผ”๏ผ•๏ผ–๏ผ—" ); # becomes -1234567
# or, to get all the defaults based on language code
my $n = Module::Generic::Number->new( 10,
{
    lang => 'fr_FR',
    # or
    # locale => 'fr_FR',
});
# this would set the decimal separator to ',', the thousand separator to ' ', and precede to 0 (false).
print( "Number is: $n\n" );
# prints: 10

(no, that Moule::Generic::Number is not a typo I made up, that's literally in the original, I am not touching it โ€” copy-paste is copy-paste ๐Ÿ’…)

and then the good stuff โ€” the methods tour:

$n ** 2 # 100
# and all other operators work

my $n_neg = Module::Generic::Number->new(-10);
$n_neg->abs # 10
$n->atan # 1.47112767430373
$n->atan2(2) # 1.37340076694502
$n->cbrt # 2.15443469003188
$n->cbrt->ceil # 3
$n->clone # Cloning the number object
$n->cos # -0.839071529076452
$n->currency # โ‚ฌ
$n->decimal # .
$n->exp # 22026.4657948067
$n->cbrt->floor # 2
$n *= 100;
$n->format # 1,000.00
$n->format(0) # 1,000
$n->format(
    precision => 0,
    # Boolean value
    decimal_fill => 0,
    thousand => ',',
    decimal => '.',
);
$n->format_binary # 1111101000
my $n2 = $n->clone;
$n2 += 24
$n2->format_bytes # 1K
$n2->format_hex # 0x400
$n2->format_money # โ‚ฌ 1,024.00
$n2->format_money( '$' ) # $1,024.00
$n2->format_negative # -1,024.00
$n2->format_picture( '(x)' ) # (1,024.00)
$n2->formatter( $new_Number_Format_object );
$n->from_binary( "1111101000" ) # 1000
$n->from_hex( "0x400" ) # 1000
my $n3 = $n->clone( 3.14159265358979323846 )->int # 3
$n3->is_even # false
$n3->is_odd # true
# Uses POSIX::signbit
$n3->is_negative # 0
$n3->is_positive # 1
$n->log # 6.90775527898214
$n->log2 # 9.96578428466209
$n->log10 # 3
$n->max( 2000 ) # 2000
$n->min( 2000 ) # 1000
$n->mod(3) # 1
my $perm = Module::Generic::Number->new( '0700' );
$perm->oct # 448
printf( "%o\n", 448 ) # 700
$n->clone( 2 )->pow( 3 ) # 8
# Change position of the currency sign
$n->precede( 1 ) # Set it to precede the number
# Change precision
$n->precision( 0 )
# Based on 1000
$n->rand # For example, returns 77.775465338589
$n->rand->int # For example, would return a random integer 77
$n->clone( 3.14159265358979323846 )->round( 4 ) # 3.1416
$n->sin # 0.826879540532003
$n2->sqrt # 32
$n->symbol # โ‚ฌ
$n->tan # 1.47032415570272
$n->thousand # ,
$n->unformat( "โ‚ฌ 1,024.00" ) # 1024

# Return the raw, underlying non-object real number
my $num = $n->real;

like??? the range??? ๐Ÿฆ‹ math girlies stay winning.


โญ VERSION โญ

v2.3.3

that's v2.3.3, write it down bestie. ๐Ÿ“


๐Ÿ’– DESCRIPTION ๐Ÿ’–

so the whole purpose of this class/package is to give you a lightweight, object-oriented way to mess with numbers. that's it. that's the dream. ๐Ÿงš

it only uses perl core functions and POSIX functions โ€” nothing extra, no heavy deps โ€” and every method in here is basically a cute little wrapper around those. lowkey elegant, ngl.

the object is overloaded, which means when you use it as a string it just hands you the embedded number:

print( "I have $n friends\n" );

which would produce: I have 1000 friends โ€” adorable, no ->numify trauma. ๐Ÿ˜ญ

and because it's overloaded, you can throw it into literally any perl operator, like:

$n /= 2 # 5
$n + 3 # 8
$n **= 2 # $n is now 64
# etc...

main character energy: the object just works. โœจ

Module::Generic::Number also handles infinity and those fake numbers, a.k.a. "NaN". it uses 2 special classes for that: Module::Generic::Infinity and Module::Generic::Nan. ๐Ÿซถ

"NaN" is super straightforward, but "Inf" or "-Inf" is a bit trickier โ€” because even though it's not a number, you can still do some stuff with it. example:

# Here the use of abs is meaningless, and just to test chaining
$inf->abs->max(10)->floor

that would yield an "Inf" object (Module::Generic::Infinity), BUT:

$inf->abs->max(10)->mod(3)

would yield a "NaN" object (Module::Generic::Nan), and of course:

$inf->abs->min(10)

would yield 10 as a Module::Generic::Number object โ€” so yeah, the result can literally become an object of a different class depending on what came out of it. plot twist. ๐Ÿ’€

operators work on the infinity object too:

my $inf = Module::Generic::Infinity->ne(-Inf);
$inf *= -1 # Yields a new infinity object with value Inf

and honestly that's all this is: basic arithmetic wrapped in objects so you get an OO interface and chaining. it doesn't do anything magical โ€” it relies on perl and POSIX for the actual computation, depending on the function. โญ


๐Ÿ‘‘ METHODS ๐Ÿ‘‘

๐ŸŽ€ new

hand it a number plus optional params and you get back a fresh Module::Generic::Number object. on error it sets an error and returns undef in scalar context, or an empty list in list context. (yes, that classic Perl dual behaviour, we know her. ๐Ÿ’…)

the possible optional parameters are:

  • decimal โ€” sets the decimal separator. you can also change or grab it later with the decimal method.
  • grouping โ€” the sizes of the groups of digits, except for currency values. unpack( "C*", $grouping ) will give you the number in question. typically 3.
  • lang โ€” give it a language tag as specified in rfc5646, and it'll pull the number format properties from the locale dictionary. it does this using setlocale in POSIX, but without disturbing your own locale settings (thank god ๐Ÿซถ). once it has the number format properties, it populates the other parameters here โ€” unless you already provided them. example:
my $n = Module::Generic::Number->new( 1000, { lang => 'fr_FR' });
$n->format # 1.000,00 โ‚ฌ

that would set the thousand separator to ".", the decimal separator to ",", the currency symbol to "โ‚ฌ", and precede to false.

my $n = Module::Generic::Number->new( 1000, {
    lang => 'fr_FR',
    precede => 1,
});

this one uses the standard default format properties, except for precede, which we set to true:

$n->format # โ‚ฌ 1.000,00

when no lang is provided, it uses the default language set on the system to retrieve the number formatting properties.

and any of those properties can be overridden by just specifying its value when you create the object. easy. โœจ

  • position_neg โ€” boolean value defining whether the negative sign (typically "-") goes at the beginning (true) or at the end (false) of negative numbers.
  • position_pos โ€” boolean value defining whether the positive sign (typically an empty string) goes at the beginning (true) or at the end (false) of positive numbers.
  • precede โ€” when true, the currency symbol goes before the number; when false, it goes after. you can also change or grab this with the precede method.
  • precede_neg โ€” when true, the currency symbol goes before the negative number; when false, it goes after. you can also change or grab this with the precede_neg method.
  • precision โ€” sets the decimal precision of the number. you can also change or grab this with the precision method.
  • sign_neg โ€” the character used to denote negative currency values, usually a minus sign.
  • sign_pos โ€” the separator between groups of digits before the decimal point, except for currency values.
  • space โ€” boolean defining whether there should be a space between the currency sign and the number value.
  • space_neg โ€” boolean defining whether there should be a space between the currency sign and the number value, for negative numbers.
  • symbol โ€” sets the currency symbol used when formatting the number as money with the format_money method. you can also change or grab this with the symbol method.
  • thousand โ€” sets the thousand separator used when formatting. you can also change or grab this with the thousand method.

๐Ÿฆ‹ abs

returns the absolute value of the number object. same as abs in perlfunc. negative? not anymore bestie. โœจ

๐ŸŒˆ as_array

returns the number object as a Module::Generic::Array object.

๐Ÿ’œ as_boolean

returns the number object as a Module::Generic::Boolean object.

๐ŸŒธ as_scalar

returns the number object as a Module::Generic::Scalar object.

๐ŸŽ€ as_string

returns the object string as a string.

my $n = Module::Generic::Number->new( 1000 );
print( "I have $n books\n" );
# I have 1000 books
# But better like ths:
printf( "I have %s bools\n", $n->format( 0 ) );
# I have 1,000 books

(that bools is coming straight from the source, I'm not the one who wrote it, I'm just the messenger ๐Ÿซถ)

โญ atan

returns the arcus tangent for the number object. see atan in POSIX.

# Assuming $n is an object for 1000
# atan2( Y, X ). Y = 1000 here
$n->atan2( 20 ) # produces 1.55079899282175

๐Ÿ’… atan2

returns the arctangent of Y/X in the range -PI to PI. see atan2 in perlfunc.

๐Ÿงš cbrt

returns the cube root. see cbrt in POSIX.

๐Ÿ”ฅ ceil

returns the smallest integer value greater than or equal to the number object. see ceil in POSIX.

# Assuming $n is an object for 3.14159265358979323846
$n->ceil # 4

๐Ÿ“ chr

returns the character matching our number object. see chr in perlfunc.

# Assuming $n is 74
$n->chr # J

๐ŸŽ€ clone

returns a clone of the current object, keeping its original formatting properties. it can take an optional number, and that number will be used:

my $n = Moduke::Generic::Number->new(1000);
# $n is no 1000 with thousand separator set to "","", etc
my $n2 = $n->clone( 2020 );
# Same properties as $n, but now the number is 2020 instead of 1000 and this is a new object

(yes, Moduke, again, verbatim, I don't make the rules ๐Ÿ’€)

๐Ÿ’– cos

returns the cosine of the number object. see cos in perlfunc.

๐ŸŒŸ currency

sets or gets the currency symbol used for formatting the number object with format_money.

๐Ÿฆ‹ decimal

sets or gets the decimal separator used for formatting the number object.

๐Ÿ’œ decimal_fill

boolean. sets or gets whether to pad the decimal with zeroes. this is used in conjunction with precision.


okay that's the end of part 1 โ€” part 2 is coming, don't leave ๐Ÿ’…

decode_lconv ๐Ÿ’–

Okay so you hand this one a hash reference that came from POSIX::localeconv, and it makes sure all its non-utf8 values are properly decoded. โœจ This is especially true for the property currency_symbol.

It returns that hash reference on success. On error, it sets an error object and returns undef in scalar context, or an empty list in list context. Slay. ๐ŸŽ€

default ๐Ÿงš

Sets the dictionary โ€” thatโ€™s a hash reference, bestie โ€” of property-value pairs used for formatting the number object. ๐Ÿ’…

encoding ๐ŸŒธ

Sets or gets the encoding of the data provided by localeconv.

There is literally no reason for you to set or change this value. Itโ€™s meant to be retrieved, and it gets set automatically once the language has been set for this object. Periodt. ๐Ÿ‘‘

exp ๐Ÿ”ฅ

Returns the natural logarithm base to the power of the number object. See "exp" in perlfunc.

# Assuming the number object is 2
$n->exp # 7.38905609893065

floor ๐Ÿฆ‹

Returns the largest integer value less than or equal to the number object. See "floor" in POSIX.

# Assuming $n is an object for 3.14159265358979323846
$n->ceil # 3

format โœจ

Provided with an optional precision, and this formats the number in a human readable way using thousand and decimal separators and floating number precision.

$n->format # 1,000.00
$n->format(
    precision => 2,
    # Override object value
    thousand => ',',
    decimal => '.',
    # Boolean
    decimal_fill => 1,
);

If the number is too large or great to work with as a regular number, but instead must be shown in scientific notation, it returns that number in scientific notation without further formatting.

Module::Generic::Number->new("0.000020000E+00")->format(7); # 2e-05

It returns a scalar object upon success, or sets an error and returns undef in scalar context or an empty list in list context if an error occurred. ๐Ÿซถ

format_binary ๐Ÿ’œ

# Assuming the number object is 1000
$n->format_binary # 1111101000

format_bytes ๐Ÿ“

# Assuming the number object is 1,234,567
$n->format_bytes # 1.18M

Provided with a hash or hash reference of options, and this formats the number with suffix K, M or G depending if it exceeds gigabytes, megabytes or kilobytes; or the IEC standard 60027 "KiB", "MiB", or "GiB" depending on the option "mode".

It returns a scalar object upon success or an error if an error occurred.

The following options are supported:

  • "base" โ€” Sets the number at which the suffix set with "kilo_suffix" is added. Default is 1024. Set to any value; the only other useful value is probably 1000.

If the mode (see below) is set to "iec" or "iec60027" then setting the "base" option returns an error.

  • "mode" โ€” This can be "trad", "traditional", "iec" or "iec60027".
  • "precision" โ€” The decimal precision. Defaults to the value set with "precision".
  • "unit" โ€” By default, this is guessed based on the value of the number, but can be explicitly specified here.

In other words, numbers greater than or equal to 1024 (or other number given by the "base" option) will be divided by 1024 and suffix set with "kilo_suffix" or "kibi_suffix" added; if greater than or equal to 1048576 (1024*1024), it will be divided by 1048576 and suffix set with "mega_suffix" or "mebi_suffix" appended to the end; etc.

Possible values are: "auto" (default), "kilo", "mega", "giga".

If a value other than "auto" is specified, that value will be used instead no matter the number. For example:

Module::Generic::Number->new( 1048576 )->format_bytes( unit => 'k' );
# Produces 1,024K and not 1M

format_hex ๐ŸŒˆ

# Assuming the number object is 1000
$n->format_hex # 0x3E8

format_money ๐Ÿ’ธ

Provided with an optional precision, and an optional currency symbol, and this formats the number accordingly. It uses the object initial value set with "precision" and "currency" if not explicitly specified โ€” literally the initial format parameters specified during object instantiation, bestie. ๐ŸŽ€

# Assuming the number object is 1000
$n->format_money # โ‚ฌ 1,000.00
$n->format_money(3) # โ‚ฌ 1,000.000

It returns a scalar object upon success or an error if an error occurred.

format_negative ๐Ÿ–ค

Provided with an optional format, or by default uses the value set with "neg_format", which must include the character "x", and this formats the number object, assuming it is negative.

For example, suitable for accounting:

$n->format_negative( '(x)' ); # (1,000)

It returns a scalar object upon success or an error if an error occurred.

format_picture ๐ŸŽจ

Formats the string based on the pattern provided, which will have the "#" characters replaced by the digits from the number.

$n->format_picture( '##,###.##' ); # 1,000.00

If the length of the integer part of $number is too large to fit, the "#" characters are replaced with asterisks ("*") instead. For examples:

# Assuming 100023
$n->format_picture( 'EUR ##,###.##' ); # EUR **,***.**
# Assuming 1.00023
$n->format_picture( 'EUR #.###,###' ); # EUR 1.002,300

The comma "," and period "." used in the example above are taken from the value set with "thousand" and "decimal" respectively. However, the "thousand" characters in the "picture" provided do not need to occur every three digits; the only use of that variable by this function is to remove leading commas (see the first example above). ๐Ÿ‘€

There may not be more than one instance of "decimal" in the "picture" provided though, or an error will be returned.

It returns a scalar object upon success or an error if an error occurred.

from_binary ๐Ÿ’ป

Returns a number object based on a binary number.

my $n2 = $n->from_binary( "1111101000" ); # 1000

from_hex ๐Ÿ”ข

Returns a number object based on an hex number.

my $n2 = $n->from_hex( "0x400" ); # 1024

gibi_suffix ๐Ÿงš

Sets or gets the gibi suffix.

giga_suffix ๐Ÿ‘‘

Sets or gets the gigabytes suffix.

grouping ๐ŸŽ€

The sizes of the groups of digits, except for currency values. unpack( "C*", $grouping ) will reveal the number in question.

int โœจ

Returns the integer portion of the number object. See "int" in perlfunc for more details.

# Assuming $n is an object for 3.14159265358979323846
$n->int # 3

is_decimal ๐Ÿ’…

Returns true if the number is a decimal number.

is_empty ๐Ÿซถ

Returns true if the length of the underlying number is zero. This always returns true, because an instance of this class can never be undef. This is here for consistency with other classes of Module::Generic. No cap. ๐Ÿ’–

is_even ๐ŸŒธ

Returns true if the number is even, i.e. if the modulus of the number divided by 2 is 0.

See "is_odd".

is_finite ๐Ÿฆ‹

Returns true if the number is finite, i.e. not infinity. See "isfinite" in POSIX.

is_float ๐Ÿ’œ

Returns true if the number is a floating decimal number. It uses "modf" in POSIX to find out.

is_infinite ๐Ÿ”ฅ

Returns true if the number is infinite. See "isinf" in POSIX.

is_int โญ

Returns true if the number is an integer. It uses "modf" in POSIX to find out.

is_nan ๐Ÿ’€

Returns true if the number is not a number, i.e. NaN. See "isnan" in POSIX.

is_neg ๐ŸŒˆ

Alias for /is_negative.

is_negative ๐Ÿ–ค

Returns true if the number object is negative, false otherwise. See "signbit" in POSIX.

is_normal ๐Ÿงš

Returns true if the argument is normal (that is, not a subnormal/denormal, and not an infinity, or a not-a-number). See "isnormal" in POSIX.

is_odd ๐Ÿ“

Returns true if the number is odd, i.e. if the modulus of the number divided by 2 is 1.

See "is_even".

is_pos ๐ŸŽ€

Alias for "is_positive".

is_positive ๐Ÿ‘‘

Returns true if the number object is positive, false otherwise. See "signbit" in POSIX.

kibi_suffix ๐Ÿ’–

Sets or gets the kibi suffix.

kilo_suffix โœจ

Sets or gets the kilobytes suffix.

lang ๐ŸŒธ

Returns the current language used for the number formatting properties.

length ๐Ÿฆ‹

Returns the number of digits this number object contains. The value returned is a Module::Generic::Number object.

locale ๐Ÿ’œ

Same as "lang".

log ๐Ÿ”ฅ

Returns the natural logarithm of the number object. See "log" in perlfunc for more details.

$n->log # 6.90775527898214

log2 โญ

Logarithm base two of the number object. See "log2" in POSIX for more details.

$n->log2 # 9.96578428466209

log10 ๐ŸŒˆ

Returns the 10-base logarithm of the number object. See "log10" in POSIX for more details.

$n->log10 # 3

max ๐Ÿงš

Returns the highest number of either the number object, or the additional number provided as argument. If the latter is undef, the number object is returned. See "fmax" in POSIX.

$n->max( 2000 ) # 2000

And thereโ€™s this little floating line chilling right here, so Iโ€™m keeping it exactly where it showed up: returns the lowest number of either the number object, or the additional number provided as argument. If the latter is undef, the number object is returned. See "fmin" in POSIX.

$n->min( 2000 ) # 2000

mebi_suffix ๐ŸŽ€

Sets or gets the mebi suffix.

mega_suffix ๐Ÿ’…

Sets or gets the megabytes suffix.

min ๐Ÿ’–

Provided with another number, and this returns the smallest of the two as an Module::Generic::Number object.

neg_format ๐Ÿ–ค

Sets or gets the format for formatting negative numbers.

Returns a scalar object.

mod ๐Ÿ”ข

Returns the remainder for the number object divided by another number provided as additional argument. See "fmod" in POSIX for more details.

# Assuming 1000
$n->mod(3) # 1

oct ๐ŸŒธ

Provided an octal value, this returns the corresponding number as an object. See "oct" in perlfunc for more details.

position_neg ๐Ÿฆ‹

Set to true or false if the negative sign (typically "-") should be positioned at the beginning (true) or at the end (false) of the number.

position_pos ๐Ÿ”ฅ

Set to true or false if the positive sign (typically "", i.e. empty, but could be set to "+") should be positioned at the beginning (true) or at the end (false) of the number.

pow โญ

Returns the number object to the power of the number provided as arguments. See "pow" in POSIX for more details.

# Assuming $n is an object representing 2
$n->pow( 3 ) # 8

precede ๐Ÿงš

Sets or gets the precede property of this object. This is used by Number::Format to determine if the currency symbol should be set before or after the number.

precede_neg ๐ŸŽ€

Sets or gets the precede_neg property of this object. This is used by Number::Format to determine if the currency symbol should be set before or after the number when it is a negative number.

precede_pos ๐Ÿ‘‘

Sets or gets the property value for precede.

1 if the currency symbol precedes the currency value for nonnegative values, 0 if it follows.

precision ๐Ÿ’–

Sets or gets the floating precision of the number.

okay so picking up right at the precision example โ€” we're mid-METHODS, no re-intro needed, bestie ๐Ÿ’…:

           # Assuming $n is an object for 3.14159265358979323846
           $n->precision( 4 );
           $n->format # 3.1416

rand

Returns a random fractional number that's greater than or equal to 0 and less than the value of the number object. Need the tea? See "rand" in perlfunc for more info. ๐ŸŽฒ

real

Read-only. This returns the real underlying number used by this class. It's giving "peek behind the curtain" energy ๐Ÿ”

round

Provided with an optional precision, this will round the number object. Internally it uses "sprintf" in perldoc to achieve that.

๐Ÿšจ This returns an error if more than 1 argument was provided. To use two arguments, use round2 โ€” no cap, that's the whole vibe.

round_zero

This will round the number using "round" in POSIX, which will return "the integer (but still as floating point) nearest to the argument" โ€” iconic quote, literally.

round2

Provided with a number and an optional precision, or by default the one set with precision, and this will round the number using an alternative approach based on "round" in Number::Format. Bestie, it's the two-argument glow-up โœจ

scalar

Same as as_string. This forces the return of the object as a raw number. Periodt.

sign_neg

Sets or gets the sign_neg property of this object. The character used to denote negative currency values, usually a minus sign. ๐Ÿ’ธ

sign_pos

Sets or gets the sign_pos property of this object. The character used to denote nonnegative currency values, usually the empty string. ๐ŸŒธ

sin

Returns the sine of the number object. See "sine" in perlfunc for more details. Math girlies rise ๐Ÿงฎ

space

Sets or gets the space property of this object. 1 if a space is inserted between the currency symbol and the currency value for non-negative values, 0 otherwise. It's giving spacing etiquette ๐Ÿ’…

space_neg

Sets or gets the space_neg property of this object. 1 if a space is inserted between the currency symbol and the currency value for negative values, 0 otherwise. Negative vibes still get formatted correctly ๐Ÿ–ค

space_pos

Sets or gets the space property. 1 if a space is inserted between the currency symbol and the currency value for nonnegative values, 0 otherwise. Positive vibes only โœจ

sqrt

Return the positive square root of the number object. See "sqrt" in perlfunc for more details. Rooting for you, bestie ๐ŸŒฑ

symbol

Set or gets the currency symbol to be used in format_money. Coin icon unlocked ๐Ÿ’ฐ

tan

Returns the tangent of the number object. See "tan" in POSIX for more details. Trig stans, this one's for you ๐Ÿ“

thousand

Set or gets the thousand separator used in formatting the number. Commas? Dots? You decide ๐ŸŽ€

TO_JSON

Special method called by JSON to transform this object into a string suitable to be added in a json data. JSON said "make it stringable" and this method ate ๐Ÿ’…

unformat

Provided with a string containing a number, and an optional hash or hash reference of options, and this returns a number as a Module::Generic::Number object.

It returns an error if the string provided does not contain any number. No number, no entry โ€” vibe check failed ๐Ÿ˜ญ

my $n = Module::Generic::Number->unformat('USD 12.95'); # 12.95
# Same
my $n = $n1->unformat('USD 12.95'); # 12.95
my $n = Module::Generic::Number->unformat('USD 12.00'); # 12
my $n = Module::Generic::Number->unformat('foobar'); # return error (undef)
my $n = Module::Generic::Number->unformat('1234-567@.8'); # 1234567.8

๐ŸŽ€ SERIALISATION ๐ŸŽ€

Serialisation by CBOR, Sereal and Storable::Improved (or the legacy Storable) is supported by this package. To that effect, the following subroutines are implemented: "FREEZE", "THAW", "STORABLE_freeze" and "STORABLE_thaw". Freeze her, thaw her, she remains iconic โ„๏ธ๐Ÿ”ฅ


๐Ÿงต THREAD-SAFETY ๐Ÿงต

Module::Generic::Number is thread-safe for all its operations, as it operates on per-object state, uses thread-safe external libraries, and synchronises locale changes to prevent race conditions.

Key considerations for thread-safety:

  • Shared Variables โ€” There are no shared variables that are modified at runtime in Module::Generic::Number, except for a lock variable used to synchronise locale changes (see below). The global $DEBUG variable (inherited from Module::Generic) is typically set before threads are created, and it is the user's responsibility to ensure thread-safety if modified at runtime:
               use threads;
               local $Module::Generic::Number::DEBUG = 0; # Set before threads
               my @threads = map
               {
                   threads->create(sub
                   {
                       my $num = Module::Generic::Number->new(1000);
                       $num->format; # Thread-safe
                   });
               } 1..5;
               $_->join for( @threads );
  • Object State โ€” Number data (e.g., "_number", formatting properties like "thousands_sep") is stored per-object, ensuring thread isolation:
               use threads;
               my @threads = map
               {
                   threads->create(sub
                   {
                       my $num = Module::Generic::Number->new(1000);
                       $num += threads->tid; # Thread-safe
                       $num->format; # Thread-safe
                   });
               } 1..5;
               $_->join for( @threads );
  • Locale Handling โ€” The init method uses "setlocale" in POSIX to retrieve locale-specific formatting properties when a lang option is specified or when detecting the system's locale. This modifies process-wide state, which could potentially cause race conditions in a multi-threaded environment. To address this, the module uses a shared lock variable ($LOCALE_LOCK) to synchronise access during locale changes, ensuring thread-safety:
               use threads;
               my @threads = map
               {
                   threads->create(sub
                   {
                       my $num = Module::Generic::Number->new( 1000, lang => 'fr_FR' );
                       $num->format; # Thread-safe
                   });
               } 1..5;
               $_->join for( @threads );

The lock ensures that only one thread can modify the locale at a time, preventing interference with other threads. One at a time, bestie โ€” no cutting the locale line ๐Ÿšฆ

  • External Libraries โ€” This module relies on POSIX functions (e.g., "atan" in POSIX, "isinf" in POSIX) for mathematical operations, which are thread-safe as they operate on local data. Math is local, drama is not ๐Ÿ’…
  • Serialisation โ€” Serialisation methods ("FREEZE", "THAW") operate on per-object state, making them thread-safe. Slay.

For debugging in threaded environments (depending on your Operating System):

           ls -l /proc/$$/fd  # List open file descriptors

๐Ÿ‘€ SEE ALSO ๐Ÿ‘€

  • Module::Generic::Scalar, Module::Generic::Array, Module::Generic::Boolean, Module::Generic::Hash, Module::Generic::Dynamic
  • Math::BigInt
  • "localeconv" in POSIX, "The localeconv function" in perllocale

The friend group is stacked, ngl ๐Ÿซถ


๐Ÿ‘‘ AUTHOR ๐Ÿ‘‘

Jacques Deguest <jack@deguest.jp> โ€” author icon, we see you โœจ


Copyright (c) 2000-2024 DEGUEST Pte. Ltd.

You can use, copy, modify and redistribute this package and associated files under the same terms as Perl itself.


this page came from perl v5.42.2, dated 2026-02-15 โ€” and that's the cute little sign-off, bestie. go format some numbers and absolutely ate ๐Ÿ’…โœจ

๐Ÿ“ฆ where this page comes from