Add Text.to_decimal (#10874)

Add `Text.to_decimal`.
Also makes renames `Decimal.with_scale` to `set_scale` and makes it public.
This commit is contained in:
GregoryTravis 2024-08-28 15:33:20 -04:00 committed by GitHub
parent 1804f317b2
commit 5fba57206a
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 114 additions and 7 deletions

View File

@ -31,6 +31,7 @@
attach warnings.][10725] attach warnings.][10725]
- [Support for creating Atoms in expressions.][10820] - [Support for creating Atoms in expressions.][10820]
- [IO.print without new line][10858] - [IO.print without new line][10858]
- [Add `Text.to_decimal`.][10874]
- [Added .floor, .ceil, .trunc to the in-memory Decimal column.][10887] - [Added .floor, .ceil, .trunc to the in-memory Decimal column.][10887]
[10614]: https://github.com/enso-org/enso/pull/10614 [10614]: https://github.com/enso-org/enso/pull/10614
@ -40,6 +41,7 @@
[10725]: https://github.com/enso-org/enso/pull/10725 [10725]: https://github.com/enso-org/enso/pull/10725
[10820]: https://github.com/enso-org/enso/pull/10820 [10820]: https://github.com/enso-org/enso/pull/10820
[10858]: https://github.com/enso-org/enso/pull/10858 [10858]: https://github.com/enso-org/enso/pull/10858
[10874]: https://github.com/enso-org/enso/pull/10874
[10887]: https://github.com/enso-org/enso/pull/10887 [10887]: https://github.com/enso-org/enso/pull/10887
#### Enso Language & Runtime #### Enso Language & Runtime

View File

@ -38,7 +38,7 @@ polyglot java import org.enso.base.numeric.Decimal_Utils
A `Decimal` value is represented internally by a Java `BigInteger` "unscaled A `Decimal` value is represented internally by a Java `BigInteger` "unscaled
value" and a "scale value". The numerical value of the `Decimal` is value" and a "scale value". The numerical value of the `Decimal` is
`(unscaledValue * 10^(-scale))`. Scale values are maintained automatically by `(unscaledValue * 10^(-scale))`. Scale values are maintained automatically by
the constructors and numerical operations. the constructors and numerical operations, but can also be set explicitly.
Scale values can allow distinctions between values that would be identical as Scale values can allow distinctions between values that would be identical as
`Float`s. For example, the following values have different internal `Float`s. For example, the following values have different internal
@ -1158,9 +1158,50 @@ type Decimal
scale : Integer scale : Integer
scale self -> Integer = self.big_decimal.scale scale self -> Integer = self.big_decimal.scale
## PRIVATE ## ADVANCED
with_scale : Integer -> Decimal GROUP Math
private with_scale self new_scale:Integer -> Decimal = ICON math
Change the scale of a Decimal.
A `Decimal` value is represented internally by a Java `BigInteger` "unscaled
value" and a "scale value". The numerical value of the `Decimal` is
`(unscaledValue * 10^(-scale))`. Scale values are maintained automatically by
the constructors and numerical operations, but can also be set explicitly.
Scale values can allow distinctions between values that would be identical as
`Float`s. For example, the following values have different internal
representations:
a = Decimal.new "2.0"
b = Decimal.new "2.00"
a == b
# => True
These two values have different internal representations, but they are still
considered the same value by `==`.
! Error Conditions
- If an explicit `scale` parameter is passed, and the scale is not
large enough to represent the number exactly, an `Arithmetic_Error`
is thrown.
> Example
Set the scale of a `Decimal`
d = dec "23.456" set_scale 4
d.internal_representation
# => [234560, 6, 4]
> Example
Get an error when using a scale that is too small.
(A scale of 2 is not enough to represent three decimal places.)
dec "23.456" set_scale 2
# => Arithmetic_Error
set_scale : Integer -> Decimal
set_scale self new_scale:Integer -> Decimal =
handle_java_exception <|
if self.scale == new_scale then self else if self.scale == new_scale then self else
Decimal.Value (self.big_decimal.setScale new_scale) Decimal.Value (self.big_decimal.setScale new_scale)

View File

@ -81,7 +81,7 @@ Decimal.from (that:JS_Object) =
True -> True ->
math_context = Math_Context.new (that.at "precision") math_context = Math_Context.new (that.at "precision")
raw_value = Decimal.from_text (that.at "value") math_context raw_value = Decimal.from_text (that.at "value") math_context
raw_value.with_scale (that.at "scale") raw_value.set_scale (that.at "scale")
False -> Error.throw (Illegal_Argument.Error "Invalid JS_Object for Decimal.") False -> Error.throw (Illegal_Argument.Error "Invalid JS_Object for Decimal.")
## PRIVATE ## PRIVATE

View File

@ -1,4 +1,5 @@
import project.Any.Any import project.Any.Any
import project.Data.Decimal.Decimal
import project.Data.Index_Sub_Range.Index_Sub_Range import project.Data.Index_Sub_Range.Index_Sub_Range
import project.Data.Locale.Locale import project.Data.Locale.Locale
import project.Data.Range.Range import project.Data.Range.Range
@ -1894,6 +1895,46 @@ Text.parse_time_of_day self format:Date_Time_Formatter=Date_Time_Formatter.iso_t
Text.parse_time_zone : Time_Zone ! Time_Error Text.parse_time_zone : Time_Zone ! Time_Error
Text.parse_time_zone self = Time_Zone.parse self Text.parse_time_zone self = Time_Zone.parse self
## GROUP Conversions
ICON convert
Convert this `Text` to a `Decimal`.
Arguments:
- scale: the optional Decimal scale to use. See `Decimal.set_scale` for more
information about Decimal scales. If this argument is not used, the default
scale is used.
> Example
Convert a `Text` to a `Decimal`.
d = "23.456".to_decimal
d == Decimal.new "23.456"
# => True
! Error Conditions
- If an explicit `scale` parameter is passed, and the scale is not
large enough to represent the number exactly, an `Arithmetic_Error`
is thrown.
> Example
Convert a `Text` to a `Decimal` with an explicit scale.
d = "23.456".to_decimal scale=4
d == Decimal.new "23.456"
# => True
> Example
Get an error when using a scale that is too small.
"23.456".to_decimal scale=2
# => Arithmetic_Error
Text.to_decimal : Integer | Nothing -> Decimal
Text.to_decimal self (scale : Integer | Nothing = Nothing) -> Decimal =
d_unscaled = Decimal.from_text self
if scale == Nothing then d_unscaled else
d_unscaled.set_scale scale
## ALIAS mid, slice, substring ## ALIAS mid, slice, substring
GROUP Selections GROUP Selections
ICON split ICON split

View File

@ -1047,6 +1047,29 @@ add_specs suite_builder =
d.unscaled_value . should_equal 123456 d.unscaled_value . should_equal 123456
d.internal_representation . should_equal [123456, 6, 3] d.internal_representation . should_equal [123456, 6, 3]
suite_builder.group "(Decimal_Spec) Decimal.set_scale" group_builder->
group_builder.specify "should be able to set the scale of a decimal" <|
dec "23.456" . set_scale 3 . should_equal (dec "23.456")
dec "23.456" . set_scale 3 . internal_representation . should_equal [23456, 5, 3]
dec "23.456" . set_scale 4 . should_equal (dec "23.456")
dec "23.456" . set_scale 4 . internal_representation . should_equal [234560, 6, 4]
group_builder.specify "setting a scale that is too small should result in an error" <|
dec "23.456" . set_scale 2 . should_fail_with Arithmetic_Error
suite_builder.group "(Decimal_Spec) Text.to_decimal" group_builder->
group_builder.specify "should be able to convert a Text to a Decimal" <|
"23.456".to_decimal . should_equal (dec "23.456")
group_builder.specify "should be able to convert a Text to a Decimal, with scale" <|
"23.456".to_decimal scale=3 . should_equal (dec "23.456")
"23.456".to_decimal scale=3 . internal_representation . should_equal [23456, 5, 3]
"23.456".to_decimal scale=4 . should_equal (dec "23.456")
"23.456".to_decimal scale=4 . internal_representation . should_equal [234560, 6, 4]
group_builder.specify "converting a Text to a Decimal with a scale that is too small should result in an error" <|
"23.456".to_decimal scale=2 . should_fail_with Arithmetic_Error
main filter=Nothing = main filter=Nothing =
suite = Test.build suite_builder-> suite = Test.build suite_builder->
add_specs suite_builder add_specs suite_builder