Double.MAX_VALUE is the maximum value a double can represent (somewhere around 1.7*10^308).

This should end in some calculation problems, if you try to subtract the maximum possible value of a data type.

Even though when you are dealing with money you should never use floating point values especially while rounding this can cause problems (you will either have to much or less money in your system then).

Answer from Kuchi on Stack Overflow
Top answer
1 of 3
45

Double.MAX_VALUE is the maximum value a double can represent (somewhere around 1.7*10^308).

This should end in some calculation problems, if you try to subtract the maximum possible value of a data type.

Even though when you are dealing with money you should never use floating point values especially while rounding this can cause problems (you will either have to much or less money in your system then).

2 of 3
16

Resurrecting the dead here, but just in case someone stumbles against this like myself. I know where to get the maximum value of a double, the (more) interesting part was to how did they get to that number.

double has 64 bits. The first one is reserved for the sign.

Next 11 represent the exponent (that is 1023 biased). It's just another way to represent the positive/negative values. If there are 11 bits then the max value is 1023.

Then there are 52 bits that hold the mantissa.

This is easily computed like this for example:

public static void main(String[] args) {

    String test = Strings.repeat("1", 52);

    double first = 0.5;
    double result = 0.0;
    for (char c : test.toCharArray()) {
        result += first;
        first = first / 2;
    }

    System.out.println(result); // close approximation of 1
    System.out.println(Math.pow(2, 1023) * (1 + result));
    System.out.println(Double.MAX_VALUE);

} 

You can also prove this in reverse order :

    String max = "0" + Long.toBinaryString(Double.doubleToLongBits(Double.MAX_VALUE));

    String sign = max.substring(0, 1);
    String exponent = max.substring(1, 12); // 11111111110
    String mantissa = max.substring(12, 64);

    System.out.println(sign); // 0 - positive
    System.out.println(exponent); // 2046 - 1023 = 1023
    System.out.println(mantissa); // 0.99999...8
🌐
Coderanch
coderanch.com › t › 670713 › java › Double-MAX
What is Double.MAX_VALUE + 1? [Solved] (Java in General forum at Coderanch)
MAX_VALUE is (2 − 2⁻⁵²) × 2¹⁰²³ and MIN_VALUE is 2⁻¹⁰⁷⁴, so if you divide the two you get approx; 2²⁰⁹⁸ which will overflow. ... Hi, Thanks for all of the help so far. The following excerpt is from the JLS (for Java 8):
🌐
Oracle
docs.oracle.com › javase › 7 › docs › api › java › lang › Double.html
Double (Java Platform SE 7 )
Otherwise, s is regarded as ... to type double by the usual round-to-nearest rule of IEEE 754 floating-point arithmetic, which includes preserving the sign of a zero value. Note that the round-to-nearest rule also implies overflow and underflow behaviour; if the exact value of s is large enough in magnitude (greater than or equal to (MAX_VALUE + ...
Find elsewhere
Top answer
1 of 3
1

Method to do the checks yourself

public static double findMax(double[] data) {
    double max = Double.MIN_VALUE;
    for (double val : data) {
        if (val > max) {
            max = val;
        }
    }
    
    return max;
}

Using the Math utility

public static double findMax2(double[] data) {
    double max = Double.MIN_VALUE;
    for (double val : data) {
        max = Math.max(val, max);
    }
    
    return max;
}

Using streams

public static double findMax3(double[] data) {
    return Arrays.stream(data).max().getAsDouble();
}

Doing your own checks

public static double findMin(double[] data) {
    double min = Double.MAX_VALUE;
    for (double val : data) {
        if (val < min) {
            min = val;
        }
    }
    
    return min;
}

Using Math utility

public static double findMin2(double[] data) {
    double min = Double.MAX_VALUE;
    for (double val : data) {
        min = Math.min(val, min);
    }
    
    return min;
}

Using streams

public static double findMin3(double[] data) {
    return Arrays.stream(data).min().getAsDouble();
}
2 of 3
0

You can do everything you want do do in a single loop. First calculate the sum for each value and then check for that sum if it is a new maximum and/ or minimum value. If any of these option is true, update the respective maximum or minimum value.

import java.util.*;

public class Application {

    public static void main(String[] args) {
        var test = new double[]{10d, 4.43d, 5.3d, -6.8d, 7.1d, 8.7d, 8.1d, 234d, -3.9d, -455.3d};
        minMaxSum(test);
    }

    public static void minMaxSum(double[] arr) {
        double acc = 0;
        // initialize the minimal value with the maximal value
        double min = Double.MAX_VALUE;
        // initialize the biggest value with the smallest possible value
        double max = Double.MIN_VALUE;
        var sum = new double[arr.length];
        // a single for loop
        for (int i = 0; i < arr.length; i++) {
            var cur = arr[i];
            // sum up adding the current value
            acc += cur;
            // save the current value in new array so we can verify the result (not actually required for the algorithm)
            sum[i] = acc;
            // if something is smaller than what we've already encountered => set new smallest value
            if(acc < min) min = acc;
            // if something is bigger than what we've already encountered => set new biggest value
            if(acc < max) max = acc;
        }
        System.out.printf("""
                Original:   %s
                Prefix-sum: %s
                Min: %s
                Max: %s
                """, Arrays.toString(arr), Arrays.toString(sum), min, max);
    }

}

Expected output:

Original:   [10.0, 4.43, 5.3, -6.8, 7.1, 8.7, 8.1, 234.0, -3.9, -455.3]
Prefix-sum: [10.0, 14.43, 19.73, 12.93, 20.03, 28.73, 36.83, 270.83, 266.93, -188.37]
Min: -188.37
Max: 270.83

As many people recommended sorting as a viable approach, here some remarks on sorting. First, yes, it would give you a correct result but there is a price to pay which is speed and well it is just an unnecessarily complex solution.

Sorting based on comparisons and without any pre-conditions cannot be done faster than in O(n log n). It is obvious that the solution above needs O(n) time thus is a complexity class faster. Also the constants (which are ignored in big-O notation) are quite small in the above solution, so even if some pre-conditions were met and you could use a special sorting algorithm like Map sort (or alike) which run in O(n) (again: under certain conditions) the above solution would still be faster and, not to mention, much simpler. So don't make your life harder than it needs to be.

🌐
Programming.Guide
programming.guide › java › double-range.html
Java: Range of a double | Programming.Guide
In Java, a double is a 64-bit IEEE 754 floating point. Double values are symmetrical around origo and has a maximum magnitude of 1.7976931348623157e308
Top answer
1 of 3
5

Try changing this:

double max = Double.MAX_VALUE;
double min = Double.MIN_VALUE;

to this:

double max = -Double.MAX_VALUE;
double min = Double.MAX_VALUE;

After all, if you start off thinking you've already seen MAX_VALUE as the highest, you're never going to see anything greater than that, are you?

EDIT: Note the use of -Double.MAX_VALUE here, instead of Double.MIN_VALUE. MIN_VALUE is the smallest positive number, whereas I assume you really want "the most strongly negative finite value".

You want the first value you read to replace both max and min. An alternative would be to use Double instead, to represent the "missing" value with null to start with:

Double max = null;
Double min = null;

if (max == null || mag > max)
{
    max = mag;
}
// Ditto for min

As a style issue, I'd also only compute the average after you've read the whole of the input - you're repeatedly overwriting the value for no reason. The only reason not to do this is to avoid having to think about the case where count is 0 (i.e. an empty file) but I'd personally handle that separately anyway - when you have no values, there simply isn't an average.

2 of 3
3

dont use Double.MIN_VALUE its not what you expect it to be

Double.MIN_VALUE its not a negative number Double.MIN_VALUE is a very small nummber its 4.9e-324; // 0x0.0000000000001P-1022

Comparing with it will break as soon as you use negative numbers

A small utility class i wrote to help with it:

public class MinMaxUtil<T extends Comparable<T>>
{
  private T minimum;
  private T maximum;

  public MinMaxUtil()
  {
    reset();
  }

  public void check( T value)
  {
    if ( minimum == null || value.compareTo(minimum) < 0  )
      minimum = value;
    if ( maximum == null || value.compareTo(maximum) > 0 )
      maximum = value;
  }

  public void check( T [] values )
  {
    for (T value : values)
      {
      check(value);
      }
  }

  public void check( Collection<T> values )
  {
    for (T value : values)
      {
      check(value);
      }
  }

  public T getMinimum()
  {
    return minimum;
  }

  public T getMaximum()
  {
    return maximum;
  }

  public void reset()
  {
    minimum = null;
    maximum = null;
  }

  @Override
  public String toString()
  {
    return "MinMaxUtil{"+
        "minimum="+minimum+
        ", maximum="+maximum+
        '}';
  }
}
Top answer
1 of 1
17

According to the Primitive Data Type docs:

Double
A 64-bit number that includes a decimal point. Doubles have a minimum value of -2^63 and a maximum value of (2^63)-1

So. (2^63)-1 gives 9223372036854775807 and -2^63 gives -9223372036854775808 if you have no decimal value.

The docs also say:

Note that scientific notation (e) for Doubles is not supported.

The docs for double.valueOf() say (my emphasis):

Returns a Double that contains the value of the specified String. As in Java, the String is interpreted as representing a signed decimal.

Given all this you would expect something like the following to throw an exception:

string maxDoubleString = '9323372036854775806';
Double maxDouble = double.valueof(maxDoubleString);
System.debug(maxDouble);

Yet you get:

21:22:17.040 (40038000)|VARIABLE_ASSIGNMENT|1|maxDoubleString|"9323372036854775806"
21:22:17.040 (40044000)|STATEMENT_EXECUTE|2
21:22:17.040 (40192000)|SYSTEM_METHOD_ENTRY|2|Double.valueOf(String)
21:22:17.040 (40225000)|HEAP_ALLOCATE|2|Bytes:12
21:22:17.040 (40236000)|SYSTEM_METHOD_EXIT|2|Double.valueOf(String)
21:22:17.040 (40254000)|VARIABLE_ASSIGNMENT|2|maxDouble|9.323372036854776E18
21:22:17.040 (40259000)|STATEMENT_EXECUTE|3
21:22:17.040 (40277000)|SYSTEM_METHOD_ENTRY|3|System.debug(ANY)
21:22:17.040 (40293000)|USER_DEBUG|3|DEBUG|9.323372036854776E18

And then you scratch your head for a bit and think that looks like scientific notation and more bits than would fit in a 64 bit signed double... Indeed, we've lost some decimal places to accommodate the notation.

So while you can't create a literal double using scientific notation you can create one outside the documented range using scientific notation and double.valueOf(). E.g.

Double myPlannedLottoWinnings = double.valueof('9.9E102');

Note that it is normally a bad idea to store currency values in a double due to the potential loss of precision.

At this stage my best guess for the maximum and minimum values would match those for Java.

The double docs for Java gives:

  • MAX_VALUE as (2-2^-52)·2^1023
    Which a few minutes on the abacus gives as 1.797693134862315708145274237317e+308
  • MIN_VALUE as 2-1074
    4.9406564584124654417656879286822e-324

What I can say is that:

  • Double maxDouble = double.valueof('1.0E308');

    "VARIABLE_ASSIGNMENT|1|maxDouble|1.0E308"

  • Double maxDouble = double.valueof('1.0E309');

    "VARIABLE_ASSIGNMENT|1|maxDouble|Infinity"

  • Double maxDouble = double.valueof('1.7976931348623157e+308d');

    "VARIABLE_ASSIGNMENT|1|maxDouble|1.7976931348623157E308"

  • Double maxDouble = double.valueof('1.7976931348623158e+308d');

    "VARIABLE_ASSIGNMENT|1|maxDouble|1.7976931348623157E308"
    No, that isn't a typo, two different inputs have produced the same result.

  • Double maxDouble = double.valueof('1.7976931348623159e+308d');

    "VARIABLE_ASSIGNMENT|1|maxDouble|Infinity"

  • Double minDouble = double.valueof('4.94065645841246544e-324d'); >"VARIABLE_ASSIGNMENT|1|minDouble|4.9E-324"

See also: Wikipedia for details about a "double-precision 64-bit IEEE 754 floating point".

Top answer
1 of 2
1

The int range issue is because you have an int literal. Use a double literal by postfixing 'd':

public static void main(String[] args) {
    assignDoubleToInt(2147483646); // One less than the maximum value an int can hold
    assignDoubleToInt(2147483647); // The maximum value an int can hold
    assignDoubleToInt(2147483648d);// One greater than the maximum value an int can hold. Causes error and does not
                                  // run.
}

I believe your equality test should be <=, also: "if the value in d is not larger than the maximum value for an int" - so if it is EQUAL to the maximum value for an int, it's valid:

public static void assignDoubleToInt(double d) {
    int i = 0;
    if (d <= Integer.MAX_VALUE)
        i = (int) d;
    System.out.println(i);
}
2 of 2
0

Integer.MAX_VALUE holds 2147483647. I am assuming this is the maximum value an int can hold?

Yes.

throws "The literal 2147483648 of type int is out of range."

You can't create an int literal representing a number outside of the int range, so 2147483647 is legal but 2147483648 is not. If you want a larger integer literal, use a long literal, with the letter L appended: 2147483648L, or a double literal with a decimal point (or D appended): 2147483648.0 (or 2147483648D).

is not the proper way to do this.

The comparison d < Integer.MAX_VALUE is legal and correct, because Integer.MAX_VALUE will be widened to a double for the comparison, and a double can be (much) larger in value than Integer.MAX_VALUE. You just need to make sure you can pass the proper value in as detailed above.

(As noted in a comment above, it should be d <= Integer.MAX_VALUE, with <=.)

Top answer
1 of 1
2

The precision of double is not capable of representing the difference between Float.MAX_VALUE and Float.MAX_VALUE+1, so a rounded result is returned. That rounded result is Float.MAX_VALUE.

Float.MAX_VALUE is 2128−2104. (Note that this is 2127+2126+2125+…+2104. That is, it is the sum of all powers of two from 2127 to 2104. In binary, it has 24 one bits, which is the number of bits in the significand1 of a float. Mathematically, it equals 2128−2104.)

When you add one to this, the mathematical result is of course 2128−2104+1. This is not representable in double, because the significand of a double is 53 bits, but from 2127 to 1 is 129 bits. You cannot fit bits for both 2127 and 1 inside the significand of a double. When a result is not representable, the nearest representable number is returned.

The representable number just below the mathematical result is 2128−2104, and the representable number just above the mathematical result is 2128−2104+275. (Note that from 2127 to 275 is 52 bits, so 275 is the smallest power of 2 that bits in a 53-bit significand where the largest bit is being scaled to 2127. Thus, we calculated this next number above 2128−2104 by adding the smallest amount to it that fits in the significand.) So we have two candidates:

  • 2128−2104, which is 1 away from 2128−2104+1.
  • 2128−2104+275, which is 2104+275−1 away from 2128−2104+1.

The former is closer, so it is chosen to be the computed result. Thus, in double, adding one to 2128−2104 produces 2128−2104.

Footnote

1 The representation of a binary floating-pont number has three parts: a sign s that is +1 or −1, a significand f that is a fixed-point number with a fixed number of bits, and an exponent e, such that the number represented is sf • 2e. The significand can be thought of just as an integer with a certain number of bits, but it is often scaled by adjusting the exponent so that the significand of normal floating-point numbers is in [1, 2). For example, 132 could be thought of as the significand 1000012 times 22 or as 1.000012 times 27.

🌐
Delft Stack
delftstack.com › home › howto › java › double max value in java
How to Double max value in Java | Delft Stack
February 14, 2024 - Here, maxValue is a variable of type double, and it is assigned the maximum finite value that can be represented by a double. In Java, Double.MAX_VALUE is a constant representing the maximum finite positive value that can be represented by the double data type.
Top answer
1 of 6
5

While others already have answered why Math.max is not variadic, they didn't answer why such a method is not created when variadic functions are introduced.

I even don't know it (there is an open bug-report) so I can only guess:

It is true that it is not implemented in Math, but if we look into Collections there is the following method:

public static <T extends Object & Comparable<? super T>> T max(
    Collection<? extends T> coll) {
  ...
}

While the type signature looks ugly (it needs to be flexible enough to handle covariance and contravariance), it can easily be used with Collections.max(Arrays.asList(-13, 12, 1337, 9)); After all the function is implemented, just in a different place.

Even better: This method can handle not only doubles, but all types implementing the Comparable interface.

Nevertheless neither your suggested solution, nor the solution in Collections is object oriented, they are just static methods. Luckily with JDK8 this will change:

import java.util.Arrays;
import java.util.List;
import java.util.Optional;

int max(List<Integer> list) {
  Optional<Integer> opt = list.stream().max((a,b) -> a-b);
  return opt.orElse(Integer.MAX_VALUE);
}

max(Arrays.asList(-13, 12, 1337, 9)); // 1337
max(Arrays.asList()); // 2147483647

For the upcoming release the collection library is reworked in Project Lambda to be more object oriented. In the example above, Lambdas are used to provide an easy and readable way to determine the max element. The following would work too:

import static java.util.Comparators.naturalOrder;

Arrays.asList(-13, 12, 1337, 9)
  .stream()
  .max(naturalOrder())
  .ifPresent(System.out::println); // 1337

Instead of max one could also use the higher order function reduce:

Arrays.asList(-13, 12, 1337, 9)
  .stream()
  .reduce((a,b) -> a > b ? a : b)
  .ifPresent(System.out::println); // 1337

Another detail is the use of Optional. It is a type to simplify error handling due to composition of higher order functions as shown in the examples above.

The lambda proposal has several advantages that make it unnecessary to implement a variadic form of Math.max:

  1. It is object oriented
  2. It is polymorphic. This means it can be used with every type of collection (List, Set, Stream, Iterator etc.)
  3. It is expressive and easy to understand
  4. It allows on-the-fly parallelization. Just change .stream() to .parallelStream()
2 of 6
5

The java.lang.Math has been introduced in JDK 1.0, long before variadic functions were introduced into the language in Java 5.

In addition, efficiency is a concern: if you need two elements most of the time, it is much faster to pass them "inline", without creating an intermediate array to hold them. This also avoids the costs of setting up a loop inside the implementation.