ballerina-lang icon indicating copy to clipboard operation
ballerina-lang copied to clipboard

[Bug]: Cast to decimal produce different results in 2201.2.3 vs 2201.3.0

Open manuranga opened this issue 2 years ago • 5 comments

import ballerina/io;

public function main() {
    io:println(<decimal>1f === 1d);
}

Above program prints true in 2201.2.3 but false in 2201.3.0. In 2201.3.0, value is equivalent to 1.0d.

manuranga avatar Dec 07 '22 09:12 manuranga

Following discussion could be useful: https://esdiscuss.org/topic/es-discuss-several-decimal-discussions We have two options.

  1. new BigDecimal(Double.toString(d))
  2. new BigDecimal(d)

Looks like we are doing 1. In the above discussion Mike Cowlishaw seems to recommend 2.

The advantage of the second approach is that ES would have 754-compliant binary -> decimal conversions from day 1

But wouldn't that violate conservation of round-trip string representation. Maybe we should do 1, but special case "integers".

manuranga avatar Dec 07 '22 12:12 manuranga

cc @gabilang @KavinduZoysa

MaryamZi avatar Dec 08 '22 03:12 MaryamZi

I will create a spec issue for this.

manuranga avatar Dec 08 '22 05:12 manuranga

Spec issue created https://github.com/ballerina-platform/ballerina-spec/issues/1196

manuranga avatar Dec 08 '22 16:12 manuranga

The results are different due to a fix added to 2201.3.0 with the commit https://github.com/ballerina-platform/ballerina-lang/commit/ab112ce62df3cf00b84315cf8911bd4a7b168a03. 2201.2.3 uses new BigDecimal(doubleValue) constructor to convert float to decimal and it has been changed to use BigDecimal.valueOf(doubleValue) which is eventually uses the canonical string representation of the double value to instantiate the BigDecimal (new BigDecimal(Double.toString(d))) in 2201.3.0. If we use new BigDecimal(doubleValue) constructor, it's going to restore the precision digits and probably rounding needs to be specified. Technically, it's more accurate than BigDecimal.valueOf() since BigDecimal tries to represent the double value as accurately as possible but less intuitive. Anyway JavaDoc on BigDecimal.valueOf says that This is generally the preferred way to convert a double (or float) into a BigDecimal, as the value returned is equal to that resulting from constructing a BigDecimal from the result of using Double.toString(double). Based on that decided to use BigDecimal.valueOf() and it'll comply with the platform specification of toString().

gabilang avatar Dec 09 '22 09:12 gabilang