Hi,

Before addressing your request I want to try to just add a little context as to 
what’s really going on (after which Joe will probably correct me). You might 
know some or all of this, but it’s a refresher for everyone (including myself).

First, the value 0.1d is a “human-friendly” representation of the actual binary 
value, which is more accurately expressed as the hex literal 
0x1.999999999999Ap-4

Notice it’s a repeating expansion, and it has to be rounded up at the end to 
make it fit into 13 hex digits.

The true decimal representation of this value is

0.1000000000000000055511151231257827021181583404541015625


If we’d rounded that last digit (A) down (to 9) we would get this instead:

0.09999999999999999167332731531132594682276248931884765625


Now, the only reason we even call this value “0.1” at all (which it is not!), 
and that Java even calls it “0.1” when it is talking to us, is simply this:

It happens to be the nearest representable value to 0.1 (which you can observe 
for yourself if you look very closely at the full decimal expansions I just 
gave).


All that this means is that the short string “0.1” becomes a suitably 
unambiguous way to refer to that number. A “shorthand” for it.


Now, the fact that BigDecimal.valueOf(0.1d) decides to produce a value with 
scale set to 1 is … interesting:


jshell> double a = 0.1

a ==> 0.1


jshell> double b = 0.2

b ==> 0.2


jshell> BigDecimal.valueOf(a).scale()

$14 ==> 1


jshell> BigDecimal.valueOf(b).scale()

$15 ==> 1


jshell> BigDecimal.valueOf(a + b).scale()

$16 ==> 17


You’ve described its behavior as “correct”, but I would question whether that’s 
really the right term for it. It feels uncomfortably arbitrary to me.


When your goal is to get the BigDecimal value “0.1” (with scale 1), the safe 
and recommended way to do that is with `new BigDecimal(“0.1”)`. Maybe some 
variation on this idea will help you in your case; I’m not sure.


Again, I’m not directly commenting on your suggestion, just providing context.




On Jan 23, 2025, at 1:20 PM, Jan Kowalski <jan7...@gmail.com> wrote:

Hi!

I’m currently working on a project that heavily relies on float values, and we 
occasionally use BigDecimal for more precise mathematical operations. However, 
I’ve noticed that the current BigDecimal constructor implementation only 
supports double, which can lead to unintentional type conversion and precision 
loss when creating a BigDecimal from a float.

The documentation suggests using BigDecimal.valueOf(double val) as the 
preferred method for converting double or float values to BigDecimal, but since 
method takes double as an argument, it leads much more often to precision loss 
when float is passed.

For example:

- BigDecimal.valueOf(0.1d) correctly produces 0.1.

- However, BigDecimal.valueOf(0.1f) produces 0.10000000149011612, which 
introduces unwanted precision artifacts.

What would you think about introducing a static factory method specifically for 
float values, such as:

public static BigDecimal valueOf(float val) {
    return new BigDecimal(Float.toString(val));
}

This addition should improve usability and ensure that float values are handled 
more precisely within the BigDecimal API

Reply via email to