Description
Introduction
The Raku core library does not have a 'modf' routine. The routine is commonly found in many popular programming languages (including Python), but it was not included in the original Raku release.
I once proposed adding one and made an elementary start at it, but soon realized it is not a trivial task due to numerical issues (see closed Rakudo PR #4432). A proper implementation in Raku would use the power inherent in the language to handle very large numbers, and the returned parts should be correct for those numbers as input to 'modf'. The routine proposed in PR #4432 followed the basic implementation as found in C and C++ with some slight modifications to take advantage of existing Raku features. PR #4432 also included tests.
In the rest of this article I will present my current view on implementing the routine from the user's perspective.
General definition of modf
in other languages
-
Given a number, return the integral and fractional parts of the number (both parts as base 10 values).
-
If the number is an integer, return zero as the fractional part.
-
Both parts will have the sign of the input.
Additional features in Raku
-
The returned values will be in a
List
of two allomorphs. -
There will be two optional parameters to allow the caller to shape the return values.
Signature
sub modf($x, $digits?, :$shape --> List) {...}
where
- $x - input number (as a number, allomorph, or string)
- $digits - number of decimal places to show (pad with zeroes on the
end if needed, or round to the desired precision) - :$shape - shape the fractional output by removing any sign and removing
a decimal point and all following zeroes for zero values
Examples
The following table shows various input formats and what is expected
to be returned. Although not evident in the table, the allomorph
output values will be bracketed by the appropriate quoting style to
retain the string appearance as shown.
Input | Digits? | Integral Part | Fractional Part | Shaped Fractional Part |
---|---|---|---|---|
1.2 | 1 | 0.2 | NC* | |
-1 | -1 | -0.0 | 0 | |
1e-10 | 10 | 0 | 0.0000000001 | NC* |
-0x10.1 | -16 | -0.0625 | 0.0625 | |
12 | 12 | 0.0 | 0 |
NC - no change from the default appearance