1

The java.lang.Math class has ceil(), floor(), round() methods, but does not have trunc() one.

At the same time I see on the practice that the .intValue() method (which does actually (int) cast) does exactly what I expect from trunc() in its standard meaning.

However I cannot find any concrete documentation which confirms that intValue() is a full equivalent of trunc() and this is strange from many points of view, for example:

  • The description "Returns the value of this Double as an int (by casting to type int)" from https://docs.oracle.com/javase/7/docs/api/java/lang/Double.html does not say anything that it "returns the integer part of the fractional number" or like that.

  • The article What is .intValue() in Java? does not say anything that it behaves like trunc().

  • All my searches for "Java trunc method" or like that didn't give anything as if I am the only one who searches for trunc() and as if I don't know something very common that everyone knows.

Can I get somehow the confirmation that I can safely use intValue() in order to get fractional numbers rounded with "trunc" mode?

Alexander Samoylov
  • 2,358
  • 2
  • 25
  • 28
  • 1
    There are pretty exhaustive details in the JLS; what's missing from that description? – Dave Newton Oct 03 '19 at 14:06
  • 2
    "*does exactly what I expect from trunc() in its standard meaning*" Perhaps it is worth defining what you expect `trunc` to do. – Michael Oct 03 '19 at 14:12
  • I think he was referring to precision loss issues, like it happens for floats. – Sterconium Oct 03 '19 at 14:16
  • *The description "Returns the value of this Double as an int (by casting to type int)"* says exactly that it "returns the integer part of the fractional number": that's what "casting a double to int" means – fantaghirocco Oct 03 '19 at 14:18
  • It is clear from the docs that the method *converts* to type int, but it is not said *in which mode* the rounding happens during conversion. I know at least 4 rounding modes: ceil, floor, round, trunc. @Michael, I expect that trunc() "returns the integer part of the fractional number" – Alexander Samoylov Oct 03 '19 at 14:22
  • 1
    The [Java 8 version](https://docs.oracle.com/javase/8/docs/api/java/lang/Double.html) of the doc for `Double.intValue()` references Java Language Specification section 5.1.3 _Narrowing Primitive Conversions_; that should explain _definitively_ what "casting a `double` to`int`" means. – Kevin Anderson Oct 03 '19 at 14:22
  • @Alexander casting's not rounding – fantaghirocco Oct 03 '19 at 14:22
  • Thanks @Kevin Anderson. This is exactly what I have searched! https://docs.oracle.com/javase/specs/jls/se7/html/jls-5.html#jls-5.1.3: "the floating-point value is rounded to an integer value V, rounding toward zero using *IEEE 754 round-toward-zero mode*". I think it is the direct answer on my question. – Alexander Samoylov Oct 03 '19 at 14:29
  • 1
    Yep! And the way I read it, "round toward zero" == truncate – Kevin Anderson Oct 03 '19 at 14:38

2 Answers2

2

So the question becomes: Is casting a double to a int equal to truncation?

The Java Language Specification may have the answer. I'll quote:

specific conversions on primitive types are called the narrowing primitive conversions:

[...]

  • float to byte, short, char, int, or long
  • double to byte, short, char, int, long, or float

A narrowing primitive conversion may lose information about the overall magnitude of a numeric value and may also lose precision and range.

[...]

A narrowing conversion of a floating-point number to an integral type T takes two steps:

  • In the first step, the floating-point number is converted either to [...] an int, if T is byte, short, char, or int, as follows:
    • If the floating-point number is NaN (§4.2.3), the result of the first step of the conversion is an int or long 0.
    • Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then there are two cases:
      • If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V.
      • Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.

Which is described in IEEE 754-1985.

Tom
  • 16,842
  • 17
  • 45
  • 54
Sterconium
  • 559
  • 4
  • 20
1

You can use floor and ceil to implement trunc

  public static double trunc(double value) { 
      return value<0 ? Math.ceil(value) : Math.floor(value);
  }

With Google Guava DoubleMath#roundToInt() you can convert that result into an int:

  public static int roundToInt(double x, RoundingMode mode) {
    double z = roundIntermediate(x, mode);
    checkInRangeForRoundingInputs(
       z > MIN_INT_AS_DOUBLE - 1.0 & z < MAX_INT_AS_DOUBLE + 1.0, x, mode);
    return (int) z;
  }

  private static final double MIN_INT_AS_DOUBLE = -0x1p31;
  private static final double MAX_INT_AS_DOUBLE = 0x1p31 - 1.0;
axelclk
  • 950
  • 9
  • 28