What is the significance of radix in Character.fordigit() in Java? - java

Could someone please help me understand the significance of radix in the Character.forDigit(int digit, int radix) method?

Choosing a suitable radix lets you produce "digits" that are not decimal digits - for example, if you pass 16 for the radix, you can produce characters for digits ten through fifteen, because counting in hex uses sixteen digits - 0 through 9, followed by A through F:
char ten = Character.forDigit(10, 16); // returns 'a'
Demo.

This is tricky because the significance isn't as obvious as it first appears. When converting a string to an integer, of course the radix matters a lot. If you are converting "101" to an integer, you will get different answers depending on whether the radix (base) is binary (2), decimal (10), octal (8), hex (16), or any other base. Similarly, when converting an integer to a string, the results (when the source is >= MAX_RADIX) are all different for the different radices.
For forDigit, the answer isn't as clear. When you're converting a number to a single character representing a digit, the answer is always the same as long as the digit is valid for the radix. Thus, Character.forDigit(11,radix) always returns 'b' for all radices 12 and up. So the only significance is in how it handles the case when the digit is not valid for the radix? That is, for binary (radix=2), forDigit only works if the digit is 0 or 1; so what should it do if you say Character.forDigit(2,2), since 2 is not a valid binary digit?
There are a few things the language designers could have done: (1) get rid of the radix parameter and put the onus on the programmer to make sure the digit is in range (which in many cases will be a given anyway); (2) throw an exception; (3) return some special value. They chose (3): if you give it a digit that isn't valid for the radix, it returns '\0', the null character. This doesn't seem to be the best choice--you're unlikely to really want to use the null character for anything, which means you have to make your own check, which means they probably should have had the method throw an exception. But there it is.
But anyway, that's the significance of radix for this method: it performs a check to make sure the argument is in range, based on the radix.

It is the base of the number. One normally uses base 10 (ie 0-9). However, you might also be interested in using hexadecimal (ie 0-9, A-F), for example. The radix would then be 16.
Example:
Character.forDigit(8, 16)=8
Character.forDigit(9, 16)=9
Character.forDigit(10, 16)=a
Character.forDigit(11, 16)=b

Related

DIfference between signed and unsigned practically

I've searched and read many previous answers concerning this difference but I still don't get somethings, for example with this line of code :
System.out.println(Integer.parseUnsignedInt("11111111111111111111111111111111", 2));
I read that Unsigned can hold a larger positive value, and no negative value. Unsigned uses the leading bit as a part of the value, while the signed version uses the left-most-bit to identify if the number is positive or negative. signed integers can hold both positive and negative numbers. A Unisgned can go larger than MAX_VALUE, so why is that sysout gives -1 which is negative. And for this line code :
System.out.println(Integer.parseInt("11111111111111111111111111111111", 2));
Why does this line gives an error(32 times 1) ? Isn't a signed int suppose to treat the first 1 as a minus, and the other 31 1's as the positive value ? (so it should give - MAX_VALUE)
Java does not have unsigned integer types. When you call parseUnsignedInt, it does not return an unsigned integer, because there is no such thing in java.
Instead, parseUnsignedInt parses the input as an unsigned 32-bit value, and then returns the signed 32-bit value with the same bits.
If you provide it with a number that has the leading bit set in its unsigned representation, it will therefore return a negative number, because all the signed numbers with that bit set are negative.
Why does this line gives an error(32 times 1) ? Isn't a signed int
suppose to treat the first 1 as a minus, and the other 31 1's as the
positive value ? (so it should give - MAX_VALUE)
It throws a NumberFormatException for exactly the same reason that
Integer.parseInt("2147483648", 10)
does. The string does not represent a number that can be represented as an int when interpreted according to the specified radix. That int uses 32 bits to represent values is only peripherally related. If you want to parse a negative value with Integer.parseInt() then the string should contain a leading minus sign:
Integer.parseInt("-1111111111111111111111111111111", 2)
or even
Integer.parseInt("-10000000000000000000000000000000", 2) // note: 32 digits
The method is not mapping bits directly to an int representation. It is interpreting the string as a textual representation of a number.
A Unsigned can go larger than MAX_VALUE, so why is that sysout gives
-1 which is negative.
Integer holds a 32-bit value. The result of parseUnsignedInt(32 one-bits, 2) is a value with all bits set. What that "means" is in the eye of the beholder. Most of Java considers integer values to be signed. The formatter used by println, for example, regards the value as signed, and the result is -1.
All you really have 'inside' the Integer is a 32-bit value. parseUnsignedInt() handles its input argument specially, but then it has to store the result in a standard Integer. There is nothing to say that the bits are supposed to be 'unsigned'. If you want to treat the value as unsigned, you can't use anything that treats it as signed, since Java really does not have an unsigned-integer type.
Isn't a signed int suppose to treat the first 1 as a minus, and the
other 31 1's as the positive value ? (so it should give - MAX_VALUE)
See other answer for this part.
The representation I think you were expecting, where the high bit indicates the sign and the rest of the bits indicates the (positive) value, is called "sign and magnitude" representation. I am unaware of any current computer that uses sign-and-magnitude for its integers (may have happened in the very early days, 1950s or so, when people were getting to grips with this stuff).

Creating a BigInteger from String and pad "0"s to it

[InputParam1:Decimal Number in String format(for Eg:30),
InputParam2:Integer to denote number of repeating 0's to append(for Eg:6)]
For converting a number from Decimal to Binary and pad digits to its front I need to perform the following steps:
Step1: BigInteger binary=new BigInteger(InputParam1,2);
-->This works when I define a BigInt with a base 16 (which I just tried when base2 failed) but not with a base 2 like above.
It throws a numberformat exception.
Step 2: String pad=StringUtils.repeat("0",InputParam2);
(to repeat 0 'InputParam2' number of times)
-->This works fine
Step 3: Need to append pad in front of binary(from Step1)
For a BigInteger, I'm not able to get something similar to .append.
So I'm trying to a)convert this BigInteger number to String and b)append pad c)convert back to BigInteger (this step I'm not able to get without creating a new BigInteger)
Any pointers on Step1 and Step3-c would be helpful please.
#1 - You haven't said what value you're passing in InputParam1, but my guess is that you're passing in something other than a string containing only '0' in '1' characters. The 'radix' parameter to the constructor tells the code how to interpret the string you're giving it. This works fine for me:
BigInteger binary=new BigInteger("1000",2);
System.out.println(binary);
How you construct the number has nothing to do with how you're eventually going to want to represent or display that number. The key idea here is that the representation of a number (hex, decimal, binary) has nothing to do with the number itself, just like leading zeros don't affect the value of number. 1111 binary, f hex, and 15 decimal are all the same number. If you pass the three of these into BigDecimal's constructor with a radix of 2, 16 and 10 respectively, you'll end up with EXACTLY the same thing in each case. The object will lose any notion of what kind of representation you used to set it to its initial value.
#3 - There is no concept of a number (int, BigInteger, etc.) with zero padding at the front, just as there's no notion of which base/radix you might use to represent a number visually. You can think about it conceptually, but that's just a way of displaying the number. It has nothing to do with the number itself.
I hadn't tried it before, but it seems there's no super simple way to format a binary value in Java with leading 0s, like there is for decimal and hex, since String.format() doesn't give a format specifier for binary. Per this StackOverflow post How to get 0-padded binary representation of an integer in java?, this seems to be about the best way to go, having converted the most accepted answer to work with BigInteger:
String str = String.format("%16s", binary.toString(2)).replace(' ', '0');
So here's all of my sample code, with output:
BigInteger binary=new BigInteger("1000",2);
System.out.println(binary);
String str = String.format("%16s", binary.toString(2)).replace(' ', '0');
System.out.println(str);
Output:
8
0000000000001000

Converting negative integer to hex value using pre-defined methods

I am a beginner in Java, and have just started learning this language.
I am learning and experimenting with examples from Herbert Schildt's book to test my understanding.
My objective is to convert negative integer to hex using in-built java methods, and then back to integer (or long). However, there are two issues that I am facing:
Issue #1: as I understand from the thread hex string to decimal conversion, Java Integer parseInt error and Converting Hexadecimal String to Decimal Integer that the converted value fffffff1 is too big to fit into Integer, so I have used Long. However, when fffffff1 is converted back to Long, I don't get -15. I get garbage value = 4294967281.
Moreover, when I type-cast the result from Long to Integer, it works well. I am not sure why Long result would show garbage value and then magically I would get the right value by just typecasting the number to integer-type. I am sure I am missing something crucial here.
Issue#2: If I don't use radix (or even change it from 16 to 4) in the method Long.parseLong(), I get an exception.
Here's my code:
public class HexByte {
public static void main(String[] args) {
byte b = (byte) 0xf1;
System.out.println("Integer value is:"+Integer.valueOf(b)); //you would get -15
int i = -15;
System.out.println("Hexadecimal value is:"+Integer.toHexString(i));
//Let's try to convert to hex and then back to integer:
System.out.println("Integer of Hexadecimal of -15 is:"+(int)Long.parseLong(Integer.toHexString(i),16 ));
//type-cast to integer works well, but not sure why
System.out.println("Integer of Hexadecimal of -15 is:"+Long.parseLong(Integer.toHexString(i),16));
//This surprisingly throws garbage value
System.out.println("Integer of Hexadecimal of -15 is:"+Long.parseLong(Integer.toHexString(i)));
//doesn't work - throws an exception
}
}
Can someone please help me? I didn't want to open duplicate threads for above issues so I have included them herewith.
Issue 1:
Negative numbers are represented using Two's Complement, which you can read more about here: wikipedia link
Basically, the left-most bit is used to determine the sign of the integer (whether it's positive or negative). A 0 means the number is positive, and a 1 means it's negative.
fffffff1 doesn't go all the way to the left, so the left-most bit when you convert that to long is a 0, which means the number is positive. When you cast it to an integer, the left bits are just dropped, and you end up somewhere in the middle of the 1s such that your leftmost digit is now a 1, so that the result is negative.
An example, with much shorter lengths for demonstration's sake:
4-bit number: 0111 -> this is positive since it starts with a 0
2-bit number using the last 2 bits of the 4-bit number: 11 -> this is negative since it starts with a 1.
Longs are like the 4-bit number in this example, and ints are like the 2-bit number. Longs have 64 bits and ints have 32 bits.
Issue 2:
If you don't specify a radix, Long.parseLong assumes base 10. You're giving it "fffffff1", and it doesn't recognize "f" as a digit in base 10 and thus throws an exception. When you specify the radix 16 then it knows "f" = 15 so there aren't any problems.

Handling large numbers

I have this problem:
A positive integer is called a palindrome if its representation in the decimal system is the same when read from left to right and from right to left. For a given positive integer K of not more than 1000000 digits, write the value of the smallest palindrome larger than K to output. Numbers are always displayed without leading zeros.
Input
The first line contains integer t, the number of test cases. Integers K are given in the next t lines.
Output
For each K, output the smallest palindrome larger than K.
Example
Input:
2
808
2133
Output:
818
2222
My code converts the input to a string and evaluates either end of the string making adjustments accordingly and moves inwards. However, the problem requires that it can take values up to 10^6 digits long, if I try to parse large numbers I get a number format exception i.e.
Integer.parseInt(LARGENUMBER);
or
Long.parseInt(LARGENUMBER);
and LARGENUMBER is out of range. can anyone think of a work around or how to handle such large numbers?
You could probably use the BigInteger class to handle large integers like this.
However, I wouldn't count on it being efficient at such massive sizes. Because it still uses O(n^2) algorithms for multiplication and conversions.
Think of your steps that you do now. Do you see something that seems a little superfluous since you're converting the number to a string to process it?
While this problem talks about integers, its doing so only to restrict the input and output characters and format. This is really a string operations question with careful selection. Since this is the case, you really don't need to actually read the input in as integers, only strings.
This will make validating the palindrome simple. The only thing you should need to work out is choosing the next higher one.

Why is there a Java radix limit?

I noticed that the max limit for a radix in Java is base 36.
Is this an arbitrary limit, or does Java have reason for limiting the radix in this way?
It's the number of decimal digits (10), plus the number of letters in the alphabet (26).
If a radix of 37 were allowed, a new character would have to be picked to represent the 37th digit. While it certainly would have been possible to pick some character, there is no obvious choice. It makes sense to just disallow larger radixes.
Very simple: 26 letters + 10 digits = 36.
In order to represent a number, traditionally digits and Latin letters are used.
For completeness, I would add that there are two constants defined in JDK:
Character.MIN_RADIX
Character.MAX_RADIX
Radix limit make sense if the output has to be readable.
In various case, the output does NOT need to be readable.
Thus indeed, a higher limit would help in such cases.
And the java langage radix limit is a weak point for java.
You can use the Base64 encoding scheme as specified in RFC 4648 and RFC 2045.
Just generate the byte representation of you int number according you needs, to be compatible with the majority of the libraries that implement Base64.

Categories

Resources