4

As I understand it, long double in C++ actually leverages the hardware architecture (at least for some architectures). Does BigDecimal in Java do this for small enough inputs?

Daishisan
  • 290
  • 1
  • 6
  • 1
    Clarify your question. `BigDecimal` is just a class which describes structure for holding arbitrary long numbers. How it can use hardware architecture? – Andremoniy Aug 23 '16 at 19:56
  • 1
    And you know: the **hardware** of Java is the Java Virtual Machine. But well, that wouldn't prevent a JIT to map a specific known construct (such as objects of BigInteger) to something very specific when creating native code ... – GhostCat Aug 23 '16 at 19:58
  • @Andremoniy I'm somewhat confused at your question. Long double in C++ is a type as well, and it clearly leverages hardware architecture. I'm basically asking does BigDecimal do something similar for numbers that can fit in say 70 bits (which is more than the 64 in a double). – Daishisan Aug 23 '16 at 20:04
  • 2
    BigDecimal is decimal. What use would it have for binary hardware floating-point numbers? – user2357112 Aug 23 '16 at 20:20
  • Some 32 bit FPUs also know a 64 bit integer Comp type. A JITter could use this to do fast(er) 64 bit math than when two 32 bit values must be used. This could be seen as (limited) hardware support, but not nearly as much as the full hardware support many hardware platforms have for IEEE 754 compatible `float` and `double` values. Some JITters could also use other hardware like SSE to speed `BigDecimals` or `BigIntegers` up. – Rudy Velthuis Aug 25 '16 at 19:07

3 Answers3

5

Does BigDecimal in Java do this for small enough inputs?

No, and it could not. Floating-point numbers are lossy, while every BigDecimal has an associated precision, and can represent exactly any number below that precision. There is no "small enough input" that can usefully be rendered as a floating point number, because even if you happen to have a BigDecimal value that can be represented exactly in floating-point notation, you'd be hard-pressed to do any sort of operations on that value and maintain the specified precision.

Put another way, the purpose of BigDecimal is to offer precision while sacrificing speed. That runs exactly contrary to floating-point, which sacrifices precision in favor of speed.


It sounds like you're asking if Java offers a way to work with long double sized floating-point numbers, and there is not. We can conclude from the fact that it's not provided that the JDK authors have never felt it was necessary to add to the language.

dimo414
  • 47,227
  • 18
  • 148
  • 244
  • 1
    Wait, are you saying that floats and doubles don't maintain a certain level of precision? I was under the impression that the IEEE standard ensured that the standard operations on them (at least for normalized numbers) were guaranteed to maintain a level of precision close to (or exactly) defined by the number of bits (i.e. 32 for float, 64 for double). – Daishisan Aug 23 '16 at 20:46
  • Floating-point numbers do have a precision, but that doesn't correspond to the notion of arithmetic precision (e.g. precise to 5 decimal places) that we generally think of. For example it is impossible to precisely represent `0.1` in floating-point; under the covers a close approximation is used instead. Wikipedia goes into [more detail](https://en.wikipedia.org/wiki/Floating_point#Accuracy_problems) about this, and there's a fun [blog](http://www.exploringbinary.com/) dedicated largely to discussing issues with floating-point math. – dimo414 Aug 23 '16 at 20:56
  • 1
    Oh I didn't realize BigDecimal was actually in base 10 (despite the name). I just assumed the decimal in the name referred to the fact that it may not be an integer. In that case, that makes sense. – Daishisan Aug 24 '16 at 13:58
  • 1
    Even if it weren't base 10 internally, the key distinction is that the class is supposed to be lossless. An imaginary `BigBinary` class would behave similarly to `BigDecimal`, and would fail if you tried to do something like `new BigBinary(new BigDecimal(".1"))` without explicitly specifying a precision. – dimo414 Aug 24 '16 at 17:00
  • OP didn't mention floating point numbers though, you did. In the question, 'hardware architecture' could be referring to BCD opcodes: https://en.wikipedia.org/wiki/Intel_BCD_opcode – Chris Hatton May 02 '23 at 05:17
1

No. BigDecimal does not leverage any hardware architecture. See for example a constructor of BigDecimal from Java Source Code.

BigDecimal(BigInteger intVal, long val, int scale, int prec) {
    this.scale = scale;
    this.precision = prec;
    this.intCompact = val;
    this.intVal = intVal;
}
Atilla Ozgur
  • 14,339
  • 3
  • 49
  • 69
  • 1
    While a good point this doesn't actually answer the question, because the JVM could swap out the `BigDecimal` implementation for specific architectures. This is what happens with `Math`, for instance. To my knowledge nothing of the sort is going on with `BigDecimal`, but looking at one particular implementation doesn't tell the whole story. – dimo414 Aug 23 '16 at 20:22
  • @dimo414 can you give me an example -- JVM could swap out the XXXX implementation for specific architectures-- so that I can read it? – Atilla Ozgur Aug 23 '16 at 20:27
  • [`Math`](https://docs.oracle.com/javase/8/docs/api/java/lang/Math.html) is the canonical example; the reference implementation included in the JDK's [`share`](http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/tip/src/share/classes/java/lang/Math.java) is likely *not* what your JVM is using. The exact behavior of `Math` is undefined and left up to individual implementations and architectures. – dimo414 Aug 23 '16 at 20:34
  • [This question](http://stackoverflow.com/q/4232231/113632) goes into more detail. – dimo414 Aug 23 '16 at 20:34
1

The most important difference between BigDecimal and typical hardware long double support is the floating point radix.

The value of a BigDecimal is an integer multiplied by a power of ten. Floating point hardware is typically based on IEEE binary floating point, and each value is an integer multiplied by a power of two.

Some calculations whose inputs are exactly representable in long double have results that incur greater rounding error in long double than in BigDecimal with a given scale. For example, 1 and 10 can both be represented exactly in both formats. The result of dividing 1 by 10 can be represented exactly in BigDecimal with scale at least 1, but not in any radix 2 format.

There are, of course, many rationals that cannot be represented exactly in either format. Consider 1/3. Even there, BigDecimal will get greater or lesser rounding error, depending on scale. The answer is unlikely to be exactly the same in long double and BigDecimal.

Doing tests on each calculation to determine whether the two formats get the same answer would destroy any performance gain from using hardware assist.

Patricia Shanahan
  • 25,849
  • 4
  • 38
  • 75