ballerina-lang
ballerina-lang copied to clipboard
[Bug]: Cast to decimal produce different results in 2201.2.3 vs 2201.3.0
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.
Following discussion could be useful: https://esdiscuss.org/topic/es-discuss-several-decimal-discussions We have two options.
new BigDecimal(Double.toString(d))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".
cc @gabilang @KavinduZoysa
I will create a spec issue for this.
Spec issue created https://github.com/ballerina-platform/ballerina-spec/issues/1196
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().