<div dir="ltr"><div>I ran the benchmark once again for a smaller float, and a bigger float, and seems like suggested implementation still outperforms current one, however as the number grows the difference seems to be less significant.</div><div><br></div><div><br></div><div dir="ltr">Benchmark (iterations) (value) Mode Cnt Score Error Units<br>BigDecimalBenchmark.newApiFloat 1000 111.111f thrpt 25 11609,412 ± 51,333 ops/s<br>BigDecimalBenchmark.newApiFloat 1000 1343453.2344f thrpt 25 10081,560 ± 74,885 ops/s<br>BigDecimalBenchmark.oldApiFloat 1000 111.111f thrpt 25 4325,049 ± 40,065 ops/s<br>BigDecimalBenchmark.oldApiFloat 1000 1343453.2344f thrpt 25 7228,148 ± 78,640 ops/s</div><div dir="ltr"><br></div><div>For value 111.111f suggested constructor outperformed current implementation by 2.68 times, but for value 1343453.2344f 1.4 times. I still think it's a change that might be worthwhile (but without breaking backwards compatbility of course), especially considering the original issue, which was a precision loss when converting float to big decimal through valueOf.</div><div dir="ltr"><br></div><div class="gmail_quote gmail_quote_container"><div dir="ltr" class="gmail_attr"><br></div><div dir="ltr" class="gmail_attr">pt., 24 sty 2025 o 12:11 Jan Kowalski <<a href="mailto:jan7493@gmail.com">jan7493@gmail.com</a>> napisał(a):<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><div dir="ltr">Thank you all for your replies! <div><br><div>I'm aware of the workaround (we are using this approach in our project) and the problematic issues with decimal conversions. However, I also think that we should make sure that the behaviour of the code is more predictable. For me and other developers, it might be confusing that values of <i>new BigDecimal(Float.toString(val))</i>, and then <i>BigDecimal.valueOf(double val)</i> are different. I'd say that, if it's possible, we should reduce the arithmetic artifacts, rather than introduce them through not really needed, and not visible at the first sight, type conversions.</div><div><br></div><div>Unfortunately, I was aware about potential backwards compatibility issues and I was curious what is your opinion on this (I also thought about introducing a factory method like fromFloat to eliminate it, but I'm not sure if it sounds like a good idea). Do you think introducing such change would be beneficial to simplify the code, or rather introduce minor precision improvement, while we still don't have 100% decimal precision?</div></div><div><br></div><div>Also out of curiosity I ran a benchmark on how lack of this constructor impacts performance, and it seems like type conversion makes it around 7 times slower, than direct Float usage</div><div><br></div><div> @Benchmark<br> public void oldApiFloat(Blackhole blackhole) {<br> for (int i = 0; i < iterations; i++) {<br> blackhole.consume(BigDecimal.valueOf(0.1f));<br> }<br> }<br><br> @Benchmark<br> public void newApiFloat(Blackhole blackhole) {<br> for (int i = 0; i < iterations; i++) {<br> blackhole.consume(valueOf(0.1f));<br> }<br> }<br><br> public static BigDecimal valueOf(float val) {<br> return new BigDecimal(Float.toString(val));<br> }<br> <br> <br> Benchmark (iterations) Mode Cnt Score Error Units<br>BigDecimalBenchmark.newApiFloat 1000 thrpt 25 28355,359 ± 502,195 ops/s<br>BigDecimalBenchmark.newApiFloat 2000 thrpt 25 14132,275 ± 206,593 ops/s<br>BigDecimalBenchmark.newApiFloat 5000 thrpt 25 5667,007 ± 71,941 ops/s<br>BigDecimalBenchmark.newApiFloat 10000 thrpt 25 2808,114 ± 32,403 ops/s<br>BigDecimalBenchmark.newApiFloat 100000 thrpt 25 278,405 ± 4,642 ops/s<br>BigDecimalBenchmark.oldApiFloat 1000 thrpt 25 3559,235 ± 40,931 ops/s<br>BigDecimalBenchmark.oldApiFloat 2000 thrpt 25 1782,190 ± 21,805 ops/s<br>BigDecimalBenchmark.oldApiFloat 5000 thrpt 25 712,045 ± 6,495 ops/s<br>BigDecimalBenchmark.oldApiFloat 10000 thrpt 25 355,959 ± 6,006 ops/s<br>BigDecimalBenchmark.oldApiFloat 100000 thrpt 25 36,239 ± 0,423 ops/s</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">pt., 24 sty 2025 o 00:59 Joseph D. Darcy <<a href="mailto:joe.darcy@oracle.com" target="_blank">joe.darcy@oracle.com</a>> napisał(a):<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex"><u></u>
<div>
<div>On 1/23/2025 2:35 PM, Remi Forax wrote:<br>
</div>
<blockquote type="cite">
<div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<div>
<div>Hello Jan,<br>
</div>
<div>what you are suggesting is not a backward compatible
change.</div>
</div>
</div>
</blockquote>
<p><br>
</p>
<p>There is a source compatibility impact, meaning that for some
call sites, the mapping of existing code using BigDecimal before
and after the addition of the overloaded method would change. That
wouldn't necessarily preclude us from making such a change (and
such changes have been made in the past), but extra caution and
analysis would be called for.</p>
<p>Cheers,</p>
<p>-Joe<br>
</p>
<p><br>
</p>
<blockquote type="cite">
<div style="font-family:arial,helvetica,sans-serif;font-size:12pt;color:rgb(0,0,0)">
<div>
<div><br>
</div>
<div>If we add BigDecimal,valueOf(float), then a program
recompiled with the new JDK may change its behavior,</div>
<div>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.</div>
<div><br>
</div>
<div>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, .</div>
<div>For the same reason, in Java, 2.0 is a double and there
is no FloatStream while there is a DoubleStream.</div>
<div><br>
</div>
<div>regards,</div>
<div>Rémi</div>
</div>
<div><br>
</div>
<hr id="m_-8459502668771584715m_-1057182989738212139zwchr"></div>
</blockquote>
</div>
</blockquote></div>
</blockquote></div></div>