blob: 900b2a0983b2df4f27e8e27e8fa3640d88640441 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package java.lang;
/**
* The wrapper for the primitive type {@code float}.
*
* @see java.lang.Number
* @since 1.0
*/
public final class Float extends Number implements Comparable<Float> {
static final int EXPONENT_BIAS = 127;
static final int EXPONENT_BITS = 9;
static final int MANTISSA_BITS = 23;
static final int NON_MANTISSA_BITS = 9;
static final int SIGN_MASK = 0x80000000;
static final int EXPONENT_MASK = 0x7f800000;
static final int MANTISSA_MASK = 0x007fffff;
private static final long serialVersionUID = -2671257302660747028L;
/**
* The value which the receiver represents.
*/
private final float value;
/**
* Constant for the maximum {@code float} value, (2 - 2<sup>-23</sup>) * 2<sup>127</sup>.
*/
public static final float MAX_VALUE = 3.40282346638528860e+38f;
/**
* Constant for the minimum {@code float} value, 2<sup>-149</sup>.
*/
public static final float MIN_VALUE = 1.40129846432481707e-45f;
/**
* Constant for the Not-a-Number (NaN) value of the {@code float} type.
*/
public static final float NaN = 0.0f / 0.0f;
/**
* Constant for the positive infinity value of the {@code float} type.
*/
public static final float POSITIVE_INFINITY = 1.0f / 0.0f;
/**
* Constant for the negative infinity value of the {@code float} type.
*/
public static final float NEGATIVE_INFINITY = -1.0f / 0.0f;
/**
* Constant for the smallest positive normal value of the {@code float} type.
*
* @since 1.6
*/
public static final float MIN_NORMAL = 1.1754943508222875E-38f;
/**
* Maximum base-2 exponent that a finite value of the {@code float} type may have.
* Equal to {@code Math.getExponent(Float.MAX_VALUE)}.
*
* @since 1.6
*/
public static final int MAX_EXPONENT = 127;
/**
* Minimum base-2 exponent that a normal value of the {@code float} type may have.
* Equal to {@code Math.getExponent(Float.MIN_NORMAL)}.
*
* @since 1.6
*/
public static final int MIN_EXPONENT = -126;
/**
* The {@link Class} object that represents the primitive type {@code
* float}.
*
* @since 1.1
*/
@SuppressWarnings("unchecked")
public static final Class<Float> TYPE
= (Class<Float>) float[].class.getComponentType();
// Note: Float.TYPE can't be set to "float.class", since *that* is
// defined to be "java.lang.Float.TYPE";
/**
* Constant for the number of bits needed to represent a {@code float} in
* two's complement form.
*
* @since 1.5
*/
public static final int SIZE = 32;
/**
* Constructs a new {@code Float} with the specified primitive float value.
*
* @param value
* the primitive float value to store in the new instance.
*/
public Float(float value) {
this.value = value;
}
/**
* Constructs a new {@code Float} with the specified primitive double value.
*
* @param value
* the primitive double value to store in the new instance.
*/
public Float(double value) {
this.value = (float) value;
}
/**
* Constructs a new {@code Float} from the specified string.
*
* @param string
* the string representation of a float value.
* @throws NumberFormatException
* if {@code string} can not be parsed as a float value.
* @see #parseFloat(String)
*/
public Float(String string) throws NumberFormatException {
this(parseFloat(string));
}
/**
* Compares this object to the specified float object to determine their
* relative order. There are two special cases:
* <ul>
* <li>{@code Float.NaN} is equal to {@code Float.NaN} and it is greater
* than any other float value, including {@code Float.POSITIVE_INFINITY};</li>
* <li>+0.0f is greater than -0.0f</li>
* </ul>
*
* @param object
* the float object to compare this object to.
* @return a negative value if the value of this float is less than the
* value of {@code object}; 0 if the value of this float and the
* value of {@code object} are equal; a positive value if the value
* of this float is greater than the value of {@code object}.
* @see java.lang.Comparable
* @since 1.2
*/
public int compareTo(Float object) {
return compare(value, object.value);
}
@Override
public byte byteValue() {
return (byte) value;
}
@Override
public double doubleValue() {
return value;
}
/**
* Tests this double for equality with {@code object}.
* To be equal, {@code object} must be an instance of {@code Float} and
* {@code floatToIntBits} must give the same value for both objects.
*
* <p>Note that, unlike {@code ==}, {@code -0.0} and {@code +0.0} compare
* unequal, and {@code NaN}s compare equal by this method.
*
* @param object
* the object to compare this float with.
* @return {@code true} if the specified object is equal to this
* {@code Float}; {@code false} otherwise.
*/
@Override
public boolean equals(Object object) {
return (object instanceof Float) &&
(floatToIntBits(this.value) == floatToIntBits(((Float) object).value));
}
/**
* Returns an integer corresponding to the bits of the given
* <a href="http://en.wikipedia.org/wiki/IEEE_754-1985">IEEE 754</a> single precision
* float {@code value}. All <em>Not-a-Number (NaN)</em> values are converted to a single NaN
* representation ({@code 0x7fc00000}) (compare to {@link #floatToRawIntBits}).
*/
public static native int floatToIntBits(float value);
/**
* Returns an integer corresponding to the bits of the given
* <a href="http://en.wikipedia.org/wiki/IEEE_754-1985">IEEE 754</a> single precision
* float {@code value}. <em>Not-a-Number (NaN)</em> values are preserved (compare
* to {@link #floatToIntBits}).
*/
public static native int floatToRawIntBits(float value);
/**
* Gets the primitive value of this float.
*
* @return this object's primitive value.
*/
@Override
public float floatValue() {
return value;
}
@Override
public int hashCode() {
return floatToIntBits(value);
}
/**
* Returns the <a href="http://en.wikipedia.org/wiki/IEEE_754-1985">IEEE 754</a>
* single precision float corresponding to the given {@code bits}.
*/
public static native float intBitsToFloat(int bits);
@Override
public int intValue() {
return (int) value;
}
/**
* Indicates whether this object represents an infinite value.
*
* @return {@code true} if the value of this float is positive or negative
* infinity; {@code false} otherwise.
*/
public boolean isInfinite() {
return isInfinite(value);
}
/**
* Indicates whether the specified float represents an infinite value.
*
* @param f
* the float to check.
* @return {@code true} if the value of {@code f} is positive or negative
* infinity; {@code false} otherwise.
*/
public static boolean isInfinite(float f) {
return (f == POSITIVE_INFINITY) || (f == NEGATIVE_INFINITY);
}
/**
* Indicates whether this object is a <em>Not-a-Number (NaN)</em> value.
*
* @return {@code true} if this float is <em>Not-a-Number</em>;
* {@code false} if it is a (potentially infinite) float number.
*/
public boolean isNaN() {
return isNaN(value);
}
/**
* Indicates whether the specified float is a <em>Not-a-Number (NaN)</em>
* value.
*
* @param f
* the float value to check.
* @return {@code true} if {@code f} is <em>Not-a-Number</em>;
* {@code false} if it is a (potentially infinite) float number.
*/
public static boolean isNaN(float f) {
return f != f;
}
@Override
public long longValue() {
return (long) value;
}
/**
* Parses the specified string as a float value.
*
* @param string
* the string representation of a float value.
* @return the primitive float value represented by {@code string}.
* @throws NumberFormatException
* if {@code string} can not be parsed as a float value.
* @see #valueOf(String)
* @since 1.2
*/
public static float parseFloat(String string) throws NumberFormatException {
return StringToReal.parseFloat(string);
}
@Override
public short shortValue() {
return (short) value;
}
@Override
public String toString() {
return Float.toString(value);
}
/**
* Returns a string containing a concise, human-readable description of the
* specified float value.
*
* @param f
* the float to convert to a string.
* @return a printable representation of {@code f}.
*/
public static String toString(float f) {
return RealToString.getInstance().floatToString(f);
}
/**
* Parses the specified string as a float value.
*
* @param string
* the string representation of a float value.
* @return a {@code Float} instance containing the float value represented
* by {@code string}.
* @throws NumberFormatException
* if {@code string} can not be parsed as a float value.
* @see #parseFloat(String)
*/
public static Float valueOf(String string) throws NumberFormatException {
return parseFloat(string);
}
/**
* Compares the two specified float values. There are two special cases:
* <ul>
* <li>{@code Float.NaN} is equal to {@code Float.NaN} and it is greater
* than any other float value, including {@code Float.POSITIVE_INFINITY};</li>
* <li>+0.0f is greater than -0.0f</li>
* </ul>
*
* @param float1
* the first value to compare.
* @param float2
* the second value to compare.
* @return a negative value if {@code float1} is less than {@code float2};
* 0 if {@code float1} and {@code float2} are equal; a positive
* value if {@code float1} is greater than {@code float2}.
* @since 1.4
*/
public static int compare(float float1, float float2) {
// Non-zero, non-NaN checking.
if (float1 > float2) {
return 1;
}
if (float2 > float1) {
return -1;
}
if (float1 == float2 && 0.0f != float1) {
return 0;
}
// NaNs are equal to other NaNs and larger than any other float
if (isNaN(float1)) {
if (isNaN(float2)) {
return 0;
}
return 1;
} else if (isNaN(float2)) {
return -1;
}
// Deal with +0.0 and -0.0
int f1 = floatToRawIntBits(float1);
int f2 = floatToRawIntBits(float2);
// The below expression is equivalent to:
// (f1 == f2) ? 0 : (f1 < f2) ? -1 : 1
// because f1 and f2 are either 0 or Integer.MIN_VALUE
return (f1 >> 31) - (f2 >> 31);
}
/**
* Returns a {@code Float} instance for the specified float value.
*
* @param f
* the float value to store in the instance.
* @return a {@code Float} instance containing {@code f}.
* @since 1.5
*/
public static Float valueOf(float f) {
return new Float(f);
}
/**
* Converts the specified float into its hexadecimal string representation.
*
* @param f
* the float to convert.
* @return the hexadecimal string representation of {@code f}.
* @since 1.5
*/
public static String toHexString(float f) {
/*
* Reference: http://en.wikipedia.org/wiki/IEEE_754-1985
*/
if (f != f) {
return "NaN";
}
if (f == POSITIVE_INFINITY) {
return "Infinity";
}
if (f == NEGATIVE_INFINITY) {
return "-Infinity";
}
int bitValue = floatToIntBits(f);
boolean negative = (bitValue & 0x80000000) != 0;
// mask exponent bits and shift down
int exponent = (bitValue & 0x7f800000) >>> 23;
// mask significand bits and shift up
// significand is 23-bits, so we shift to treat it like 24-bits
int significand = (bitValue & 0x007FFFFF) << 1;
if (exponent == 0 && significand == 0) {
return (negative ? "-0x0.0p0" : "0x0.0p0");
}
StringBuilder hexString = new StringBuilder(10);
if (negative) {
hexString.append("-0x");
} else {
hexString.append("0x");
}
if (exponent == 0) { // denormal (subnormal) value
hexString.append("0.");
// significand is 23-bits, so there can be 6 hex digits
int fractionDigits = 6;
// remove trailing hex zeros, so Integer.toHexString() won't print
// them
while ((significand != 0) && ((significand & 0xF) == 0)) {
significand >>>= 4;
fractionDigits--;
}
// this assumes Integer.toHexString() returns lowercase characters
String hexSignificand = Integer.toHexString(significand);
// if there are digits left, then insert some '0' chars first
if (significand != 0 && fractionDigits > hexSignificand.length()) {
int digitDiff = fractionDigits - hexSignificand.length();
while (digitDiff-- != 0) {
hexString.append('0');
}
}
hexString.append(hexSignificand);
hexString.append("p-126");
} else { // normal value
hexString.append("1.");
// significand is 23-bits, so there can be 6 hex digits
int fractionDigits = 6;
// remove trailing hex zeros, so Integer.toHexString() won't print
// them
while ((significand != 0) && ((significand & 0xF) == 0)) {
significand >>>= 4;
fractionDigits--;
}
// this assumes Integer.toHexString() returns lowercase characters
String hexSignificand = Integer.toHexString(significand);
// if there are digits left, then insert some '0' chars first
if (significand != 0 && fractionDigits > hexSignificand.length()) {
int digitDiff = fractionDigits - hexSignificand.length();
while (digitDiff-- != 0) {
hexString.append('0');
}
}
hexString.append(hexSignificand);
hexString.append('p');
// remove exponent's 'bias' and convert to a string
hexString.append(exponent - 127);
}
return hexString.toString();
}
}