Hello Jan, what you are suggesting is not a backward compatible change. If we add BigDecimal,valueOf(float), then a program recompiled with the new JDK may change its behavior, you can think that the new behavior is more "correct" that the current one, but changing the behavior of existing programs is usually a big NO ! in Java.
Also, I believe that the reason there is no such factory method that takes a float is that doing computations on floats is not recommanded, it becomes a mess rapidly of the imprecision of the float32 representation, . For the same reason, in Java, 2.0 is a double and there is no FloatStream while there is a DoubleStream. regards, Rémi > From: "Kevin Bourrillion" <kevin.bourrill...@oracle.com> > To: "Jan Kowalski" <jan7...@gmail.com> > Cc: "core-libs-dev" <core-libs-dev@openjdk.org> > Sent: Thursday, January 23, 2025 10:46:51 PM > Subject: Re: Adding BigDecimal.valueOf(float val) constructor > 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