If the radix is smaller than {@code Character.MIN_RADIX} + * or larger than {@code Character.MAX_RADIX}, then the radix + * {@code 10} is used instead. + * + *

Note that since the first argument is treated as an unsigned + * value, no leading sign character is printed. + * + *

If the magnitude is zero, it is represented by a single zero + * character {@code '0'} (`'\u0030'`); otherwise, + * the first character of the representation of the magnitude will + * not be the zero character. + * + *

The behavior of radixes and the characters used as digits + * are the same as {@link #toString(long, int) toString}. + * + * @param i an integer to be converted to an unsigned string. + * @param radix the radix to use in the string representation. + * @return an unsigned string representation of the argument in the specified radix. + * @see #toString(long, int) + * @since 1.8 + */ + public static String toUnsignedString(long i, int radix) { + if (i >= 0) + return toString(i, radix); + else { + switch (radix) { + case 2: + return toBinaryString(i); + + case 4: + return toUnsignedString0(i, 2); + + case 8: + return toOctalString(i); + + case 10: + /* + * We can get the effect of an unsigned division by 10 + * on a long value by first shifting right, yielding a + * positive value, and then dividing by 5. This + * allows the last digit and preceding digits to be + * isolated more quickly than by an initial conversion + * to BigInteger. + */ + long quot = (i >>> 1) / 5; + long rem = i - quot * 10; + return toString(quot) + rem; + + case 16: + return toHexString(i); + + case 32: + return toUnsignedString0(i, 5); + + default: + return toUnsignedBigInteger(i).toString(radix); + } + } + } + + /** + * Return a BigInteger equal to the unsigned value of the + * argument. + */ + private static BigInteger toUnsignedBigInteger(long i) { + if (i >= 0L) + return BigInteger.valueOf(i); + else { + int upper = (int) (i >>> 32); + int lower = (int) i; + + // return (upper << 32) + lower + return (BigInteger.valueOf(Integer.toUnsignedLong(upper))).shiftLeft(32). + add(BigInteger.valueOf(Integer.toUnsignedLong(lower))); + } + } + + /** * Returns a string representation of the {@code long} * argument as an unsigned integer in base 16. * @@ -147,12 +230,18 @@ * 264 if the argument is negative; otherwise, it is * equal to the argument. This value is converted to a string of * ASCII digits in hexadecimal (base 16) with no extra - * leading {@code 0}s. If the unsigned magnitude is zero, it - * is represented by a single zero character {@code '0'} - * (`'\u0030'`); otherwise, the first character of - * the representation of the unsigned magnitude will not be the - * zero character. The following characters are used as - * hexadecimal digits: + * leading {@code 0}s. + * + *

The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, + * 16)}. + * + *

If the unsigned magnitude is zero, it is represented by a + * single zero character {@code '0'} (`'\u0030'`); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * following characters are used as hexadecimal digits: * *

* {@code 0123456789abcdef} @@ -172,10 +261,12 @@ * @return the string representation of the unsigned {@code long} * value represented by the argument in hexadecimal * (base 16). + * @see #parseUnsignedLong(String, int) + * @see #toUnsignedString(long, int) * @since JDK 1.0.2 */ public static String toHexString(long i) { - return toUnsignedString(i, 4); + return toUnsignedString0(i, 4); } /** @@ -188,12 +279,16 @@ * ASCII digits in octal (base 8) with no extra leading * {@code 0}s. * + *

The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, + * 8)}. + * *

If the unsigned magnitude is zero, it is represented by a - * single zero character {@code '0'} - * (`'\u0030'`); otherwise, the first character of - * the representation of the unsigned magnitude will not be the - * zero character. The following characters are used as octal - * digits: + * single zero character {@code '0'} (`'\u0030'`); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * following characters are used as octal digits: * *

* {@code 01234567} @@ -205,10 +300,12 @@ * @param i a {@code long} to be converted to a string. * @return the string representation of the unsigned {@code long} * value represented by the argument in octal (base 8). + * @see #parseUnsignedLong(String, int) + * @see #toUnsignedString(long, int) * @since JDK 1.0.2 */ public static String toOctalString(long i) { - return toUnsignedString(i, 3); + return toUnsignedString0(i, 3); } /** @@ -219,27 +316,35 @@ * 264 if the argument is negative; otherwise, it is * equal to the argument. This value is converted to a string of * ASCII digits in binary (base 2) with no extra leading - * {@code 0}s. If the unsigned magnitude is zero, it is - * represented by a single zero character {@code '0'} - * (`'\u0030'`); otherwise, the first character of - * the representation of the unsigned magnitude will not be the - * zero character. The characters {@code '0'} - * (`'\u0030'`) and {@code '1'} - * (`'\u0031'`) are used as binary digits. + * {@code 0}s. + * + *

The value of the argument can be recovered from the returned + * string {@code s} by calling {@link + * Long#parseUnsignedLong(String, int) Long.parseUnsignedLong(s, + * 2)}. + * + *

If the unsigned magnitude is zero, it is represented by a + * single zero character {@code '0'} (`'\u0030'`); + * otherwise, the first character of the representation of the + * unsigned magnitude will not be the zero character. The + * characters {@code '0'} (`'\u0030'`) and {@code + * '1'} (`'\u0031'`) are used as binary digits. * * @param i a {@code long} to be converted to a string. * @return the string representation of the unsigned {@code long} * value represented by the argument in binary (base 2). + * @see #parseUnsignedLong(String, int) + * @see #toUnsignedString(long, int) * @since JDK 1.0.2 */ public static String toBinaryString(long i) { - return toUnsignedString(i, 1); + return toUnsignedString0(i, 1); } /** * Convert the integer to an unsigned number. */ - private static String toUnsignedString(long i, int shift) { + private static String toUnsignedString0(long i, int shift) { char[] buf = new char[64]; int charPos = 64; int radix = 1 << shift; @@ -271,6 +376,24 @@ } /** + * Returns a string representation of the argument as an unsigned + * string. + * + * The argument is converted to unsigned decimal representation + * and returned as a string exactly as if the argument and radix + * 10 were given as arguments to the {@link #toUnsignedString(long, + * int)} method. + * + * @param i an integer to be converted to an unsigned string. + * @return an unsigned string representation of the argument. + * @see #toUnsignedString(long, int) + * @since 1.8 + */ + public static String toUnsignedString(long i) { + return toUnsignedString(i, 10); + } + + /** * Places characters representing the integer i into the * character array buf. The characters are placed into * the buffer backwards starting with the least significant @@ -485,6 +608,121 @@ } /** + * Parses the string argument as an unsigned {@code long} in the + * radix specified by the second argument. An unsigned integer + * maps the values usually associated with negative numbers to + * positive numbers larger than {@code MAX_VALUE}. + * + * The characters in the string must all be digits of the + * specified radix (as determined by whether {@link + * java.lang.Character#digit(char, int)} returns a nonnegative + * value), except that the first character may be an ASCII plus + * sign {@code '+'} (`'\u002B'`). The resulting + * integer value is returned. + * + *

An exception of type {@code NumberFormatException} is + * thrown if any of the following situations occurs: + *

+ *
• The first argument is {@code null} or is a string of + * length zero. + * + *
• Any character of the string is not a digit of the specified + * radix, except that the first character may be a plus sign + * {@code '+'} (`'\u002B'`) provided that the + * string is longer than length 1. + * + *
+ * + * + * @param s the {@code String} containing the unsigned integer + * representation to be parsed + * @param radix the radix to be used while parsing {@code s}. + * @return the integer represented by the string argument in the + * specified radix. + * @throws NumberFormatException if the {@code String} + * does not contain a parsable {@code long}. + * @since 1.8 + */ + public static long parseUnsignedLong(String s, int radix) + throws NumberFormatException { + if (s == null) { + throw new NumberFormatException("null"); + } + + int len = s.length(); + if (len > 0) { + char firstChar = s.charAt(0); + if (firstChar == '-') { + throw new + NumberFormatException(String.format("Illegal leading minus sign " + + "on unsigned string %s.", s)); + } else { + if (len <= 12 || // Long.MAX_VALUE in Character.MAX_RADIX is 13 digits + (radix == 10 && len <= 18) ) { // Long.MAX_VALUE in base 10 is 19 digits + return parseLong(s, radix); + } + + // No need for range checks on len due to testing above. + long first = parseLong(s.substring(0, len - 1), radix); + int second = Character.digit(s.charAt(len - 1), radix); + if (second < 0) { + throw new NumberFormatException("Bad digit at end of " + s); + } + long result = first * radix + second; + if (compareUnsigned(result, first) < 0) { + /* + * The maximum unsigned value, (2^64)-1, takes at + * most one more digit to represent than the + * maximum signed value, (2^63)-1. Therefore, + * parsing (len - 1) digits will be appropriately + * in-range of the signed parsing. In other + * words, if parsing (len -1) digits overflows + * signed parsing, parsing len digits will + * certainly overflow unsigned parsing. + * + * The compareUnsigned check above catches + * situations where an unsigned overflow occurs + * incorporating the contribution of the final + * digit. + */ + throw new NumberFormatException(String.format("String value %s exceeds " + + "range of unsigned long.", s)); + } + return result; + } + } else { + throw NumberFormatException.forInputString(s); + } + } + + /** + * Parses the string argument as an unsigned decimal {@code long}. The + * characters in the string must all be decimal digits, except + * that the first character may be an an ASCII plus sign {@code + * '+'} (`'\u002B'`). The resulting integer value + * is returned, exactly as if the argument and the radix 10 were + * given as arguments to the {@link + * #parseUnsignedLong(java.lang.String, int)} method. + * + * @param s a {@code String} containing the unsigned {@code long} + * representation to be parsed + * @return the unsigned integer value represented by the argument in decimal. + * @throws NumberFormatException if the string does not contain a + * parsable unsigned integer. + * @since 1.8 + */ + public static long parseUnsignedLong(String s) throws NumberFormatException { + return parseUnsignedLong(s, 10); + } + + /** * Returns a {@code Long} object holding the value * extracted from the specified {@code String} when parsed * with the radix given by the second argument. The first @@ -977,6 +1215,86 @@ return (x < y) ? -1 : ((x == y) ? 0 : 1); } + /** + * Compares two {@code long} values numerically treating the values + * as unsigned. + * + * @param x the first {@code long} to compare + * @param y the second {@code long} to compare + * @return the value {@code 0} if {@code x == y}; a value less + * than {@code 0} if {@code x < y} as unsigned values; and + * a value greater than {@code 0} if {@code x > y} as + * unsigned values + * @since 1.8 + */ + public static int compareUnsigned(long x, long y) { + return compare(x + MIN_VALUE, y + MIN_VALUE); + } + + + /** + * Returns the unsigned quotient of dividing the first argument by + * the second where each argument and the result is interpreted as + * an unsigned value. + * + *