Convert string to byte getting number format exception - java

public class HelloWorld{
public static void main(String []args){
String str = "100.00";
Short sObj2 = Short.valueOf(str);
System.out.println(sObj2);
}
}
Getting below exception :
Exception in thread "main" java.lang.NumberFormatException: For input string: "100.00"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Integer.parseInt(Integer.java:580)
at java.lang.Short.parseShort(Short.java:118)
at java.lang.Short.valueOf(Short.java:174)
at java.lang.Short.valueOf(Short.java:200)
at HelloWorld.main(HelloWorld.java:5)
How to resolve above issue?

First a Short is not a byte (your question summary indicates you are trying to convert a string to a byte). A Short holds integer values from -32,768 to 32,767 (inclusive). Trying to parse a floating point value into an integer datatype causes this exception.
If you simply want code that will run without an exception, either of the following should work:
public class HelloWorld{
public static void main(String []args){
String str = "100";
Short sObj2 = Short.valueOf(str);
System.out.println(sObj2);
}
}
This first example makes it run by changing the string to an integer value.
or
public class HelloWorld{
public static void main(String []args){
String str = "100.00";
Double sObj2 = Double.valueOf(str);
System.out.println(sObj2);
}
}
This second one works by parsing a string representing a floating point value into a variable type that supports floating points.

Try this
String str = "100";
Short sObj2 = Short.valueOf(str);
or if you want to deal with decimal values,
String str = "100.00";
Float fObj2 = Float.valueOf(str);

To begin with, as your post title suggests, you want to convert from a String data type to a byte data type. This doesn't necessarily include just displaying the a value which doesn't generate a NumberFormatException error. I'm assuming you actually want to work with those particular data types.
To throw a small twist into things, you want to convert all this from a string representation of a numerical value which can be from either a float or double data type ("100.00"). It's this decimal point within the numerical string that throws a glitch into things when doing any conversion and therefore needs to be handled before doing any such thing.
Some things to consider:
As a String, you can represent any number you like in any format you like. It can be as big as you want and it can be as small as you want. I can even be a number that is imaginary or doesn't exist, but the bottom line is....it will always be a String and you can do such things with String data types. Converting a String numerical value to an actual numerical data type such as byte, short, integer, long, double, float, etc is a different ball game altogether. Some String numerical values are easy to convert and yet some require more specific attention to detail.
A byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive).
A short data type is a 16-bit signed two's complement integer. It has a minimum value of -32,768 and a maximum value of 32,767 (inclusive).
The int (integer) data type is a 32-bit signed two's complement integer, which has a minimum value of -2147483648 and a maximum value of 2147483647.
The long data type is a 64-bit two's complement integer. The signed long has a minimum value of -9223372036854775808 and a maximum value of 9223372036854775807.
At the end of it all these four data types all maintain integer values with each data type also maintaining a minimum and maximum of values. You need to also consider this to some extent when doing data type conversions. If you are going to create a conversion method to convert from one data type to another you need to ensure that you do not exceed that minimum and maximum allowable value for the data type you want to convert to. Not a big deal if you want to convert a byte data type to a short data type or a short to an integer since we know that the lesser will always play in the larger but this is not necessarily so when a larger is to play in a lesser (short to byte).
Your conversion method needs to check the value to convert so as to ensure it will actually fit into the desired data type. Java has constants to assist you with this so that you don't have to remember these minimums and maximums, for example: Integer.MIN_VALUE and Integer.MAX_VALUE or Byte.MIN_VALUE and Byte.MAX_VALUE.
When dealing with numerical strings you may also want to ensure that the string you're dealing with is actually a string representation of a numerical value and not a alphanumeric value such as that of a Hexidecimal string or just a plain out entry error whereas a character other than a digit has crept into the string somehow. In my opinion, the string: "100.00" is a string representation of both a alphanumeric value (because of the period) and a numeric value since it is a string representation of a double data type. What it will truly be depends upon how you handle the period (decimal point) in the string within your conversion method.
Let's take another look at that string value ("100.00"). Another thing you may want to consider is, what if our string value was: "100.74"? How do you want to handle this particular value? Do you want to Round Down to 100 or *Round Up to 101 before you convert it to a data type that requires a integer value?
Let's convert the String representation of the value "100.00" to a short data type. Now keep in mind that the methods I provide below by default will always convert a string representation of a double data type (if supplied) downwards, for example 100.45 or 100.99 will be 100. If you want to properly round up or down for this type of value then supply a boolean true in the optional roundUpDown argument:
private short StringToShort(final String input, final boolean... roundUpDown) {
// Make sure there no dead whitespaces...
String inputValue = input.replaceAll(" ", "");
int i = 0; // default return value is 0
// If inputValue contains nothing ("") then return 0
if(inputValue.equals("")) { return 0; }
// Is inputValue an actual numerical value?
// Throws an exception if not.
// Handles negative and decimal point...
if (!inputValue.matches("-?\\d+(\\.\\d+)?")) {
throw new IllegalArgumentException("\nStringToShort() Method Error!\n"
+ "The value supplied is not numeric (" + inputValue + ").\n");
}
// Was the optional roundUpDown argument supplied?
boolean round = false; // default is false
if (roundUpDown.length > 0) { round = roundUpDown[0]; }
// Convert the String to a Integer value
if (inputValue.contains(".")) {
// Must be a double type representation supplied
Double value = Double.parseDouble(inputValue);
if (round) { i = (int) Math.round(value); }
else { i = (int) value.intValue(); }
}
else {
// Must be a Integer type representation supplied
i = Integer.parseInt(inputValue);
}
// Is the Integer value now too small or too
// large to be a Short data type?
if (i > Short.MAX_VALUE || i < Short.MIN_VALUE) {
throw new IllegalArgumentException("\nStringToShort() Method Error!\n"
+ "The value supplied is too small or too large (" + inputValue + ").\n"
+ "Only values from " + Short.MIN_VALUE + " to " + Short.MAX_VALUE
+ " are allowed!\n");
}
// Finally, cast and return a short data type...
return (short) i;
}
If you read all the comments within the code you can see that we've covered all the issues discussed above. Now, according to your post title, you wanted to convert to byte. Well, it's pretty much the very same method but with perhaps five or so small changes done, see if you can spot them:
private byte StringToByte(final String input, final boolean... roundUpDown) {
// Make sure there no dead whitespaces...
String inputValue = input.replaceAll(" ", "");
int i = 0; // default return value is 0
// If inputValue contains nothing ("") then return 0
if(inputValue.equals("")) { return 0; }
// Is inputValue an actual numerical value?
// Throws an exception if not.
// Handles negative and decimal point...
if (!inputValue.matches("-?\\d+(\\.\\d+)?")) {
throw new IllegalArgumentException("\nStringToByte() Method Error!\n"
+ "The value supplied is not numeric (" + inputValue + ").\n");
}
// Was the optional roundUpDown argument supplied?
boolean round = false; // default is false
if (roundUpDown.length > 0) { round = roundUpDown[0]; }
// Convert the String to a Integer value
if (inputValue.contains(".")) {
// Must be a double type representation supplied
Double value = Double.parseDouble(inputValue);
if (round) { i = (int) Math.round(value); }
else { i = (int) value.intValue(); }
}
else {
// Must be a Integer type representation supplied
i = Integer.parseInt(inputValue);
}
// Is the Integer value now too small or too
// large to be a Byte data type?
if (i > Byte.MAX_VALUE || i < Byte.MIN_VALUE) {
throw new IllegalArgumentException("\nStringToByte() Method Error!\n"
+ "The value supplied is too small or too large (" + inputValue + ").\n"
+ "Only values from " + Byte.MIN_VALUE + " to " + Byte.MAX_VALUE
+ " are allowed!\n");
}
// Finally, cast and return a byte data type...
return (byte) i;
}

Related

Why am I getting a number format exception when the data type accepts the values im parsing?

I do not want the answer, I would just like guidance and for someone to point to why my code is not performing as expected
My task is to flip an integer into binary, reformat the binary to a 32 bit number and then return the unsigned integer. So far my code successfully makes the conversions and flips the bits however I am getting a NumberFormatException when I attempt to parse the string value into a long that ill convert to an unsigned integer.
What is the issue with my code? What have I got misconstrued here? I know there are loads of solutions to this problem online but I prefer working things out my own way?
Could I please get some guidance? Thank you
public class flippingBits {
public static void main(String[] args) {
//change the number to bits
long bits = Long.parseLong(Long.toBinaryString(9));
String tempBits = String.valueOf(bits);
//reformat so that you get 32 bits
tempBits = String.format("%" + (32) + "s", tempBits).replace(" ", "0");
//flip the bits
tempBits = tempBits.replace("1", "5");
tempBits = tempBits.replace("0", "1");
tempBits = tempBits.replace("5", "0");
//Pass this to a long data type so that you can then eventually convert the new bits
// to an unsigned integer
long backToNum = Long.parseLong(tempBits);
}
}
You're directly parsing the bits into a long value instead of converting the bits into an equivalent value.
You need to use the following method (Long.parseUnsignedLong()):
long backToNum = Long.parseUnsignedLong(tempBits, 2); //output: 4294967286
The second argument represents radix:
To interpret a number written in a particular representation, it is necessary to know the radix or base of that representation. This allows the number to be converted into a real value.
See the representation of each radix (From Wikipedia):

XPTY0004: Required item type of first operand of '>' is numeric; supplied value has item type xs:string

The toComplie string contains all the definitions of the functions like sum, multiply, etc. appended by if ($a > 0) then (iaf:numeric-equal(iaf:numeric-multiply($b, $c), $d)) else (true())
The snippet executing this is :
XQueryExecutable queryExecutable = xqueryCompiler.compile(toCompile.toString());
XQueryEvaluator xqueryEvaluator = queryExecutable.load();
//setExternalVariables(): function used to set the variables for the test contains below line
xqueryEvaluator.setExternalVariable(new QName(memberName), value);
setExternalVariables(xqueryEvaluator,assertionExpression);
xqueryResult = xqueryEvaluator.evaluate();
Which throws an exception as below:
XPTY0004: Required item type of the first operand of '>' is numeric; supplied value has item type xs:string
Please let me know if any more information is needed to understand the question. Is this because of the else part, or something else?
EDIT:
In setExternalVariables(), I'm adding the variables using below line, using for-each loop. value variable is of type net.sf.saxon.s9api.XdmValue
xqueryEvaluator.setExternalVariable(new QName(memberName), value);
In setExternalVariables() method,
// FACT_VALUE_FORMAT:%s;%s -- where first string is value and second gives information about precision.
//current option
XdmAtomicValue atomicValue = new XdmAtomicValue(String.format(FACT_VALUE_FORMAT, fact.getValue(),getPrecision(fact.getDecimals())));
// alternative 1
atomicValue = new XdmAtomicValue(getDoubleValue(fact));
//alternative 2
atomicValue = new XdmAtomicValue(getStringValue(fact));
In getDoubleValue(),
String precision = fact.getDecimals();
BigDecimal value = new BigDecimal(fact.getValue());
if((precision != null ) && (precision.equals(INF_STRING) == false )){
if(Integer.parseInt(precision)>0){
NumberFormat nf = NumberFormat.getNumberInstance(Locale.US);
DecimalFormat df = (DecimalFormat)nf;
// If the decimal value is greater than 0, then we need the decimal precision correct to n places of decimal
df.setMaximumFractionDigits(Integer.parseInt(precision) + 1);
double doublePrecision = Math.pow(10,-Integer.parseInt(precision))/2;
df.setMaximumFractionDigits(Integer.parseInt(precision) + 1);
precision = df.format(doublePrecision);
System.out.println("doublePrecision\t:\t"+doublePrecision);
return (double) Math.round(value.doubleValue() * doublePrecision) / doublePrecision;
}else{
int scale = (int) Math.pow(10, -Integer.parseInt(precision));
System.out.println("scale\t:\t"+scale);
return (double) Math.round(value.doubleValue() * scale) / scale;
}
}
return value.doubleValue();
In getStringValue(),
String value = fact.getValue();
String decimal = fact.getDecimals();
String DOT = "\\.";
if(value.contains(".")){
final int parseInt = Integer.parseInt(decimal);
if(parseInt>0){
String[]split = value.split(DOT);
value = split[0];
if(parseInt>=value.length()){
return "0";
}
for (int i = 0; i < parseInt; i++) {
char[] array =value.toCharArray();
array[value.length()-i-1]="0".charAt(0);
value = new String(array);
}
}else{
final int parseNegativeInt = -Integer.parseInt(decimal);
String[]split = value.split(DOT);
String tempValue = split[1];
if(tempValue.length()>parseNegativeInt){
tempValue = tempValue.substring(0, parseNegativeInt);
}
value = split[0]+"."+tempValue;
}
}
return value;
Current implementation and alternative(2) does not work for the rule mentioned above, and when I'm returning double, it transforms big numbers into expression containing char E, for e.g. 5.12344E12, which fails in other rules.
Error on line 199 of module with no systemId:
FORG0001: Cannot convert string "1.089563E9" to xs:decimal: invalid character 'E'
at iaf:splitValueThreshold() (module with no systemId#20)
at iaf:numeric-equal() (module with no systemId#343)
Please suggest any other option.
Typically XPath > implicitly converts a string operand to a number, but you can force the conversion using the number() XPath function.
if (number($a) > 0) then (iaf:numeric-equal(iaf:numeric-multiply($b, $c), $d)) else (true())
Assuming you have your numeric values on the Java side as Strings in e.g. String value = "2179.125955"; then I would suggest to pass them as xs:decimals to XQuery/XPath by using new XdmAtomicValue(new BigDecimal(value)) as the value you pass to setExternalVariable e.g.
xqueryEvaluator.setExternalVariable(new QName(memberName), new XdmAtomicValue(new BigDecimal(value)));
I second Martin's suggestion (I had first overlooked BigDecimal vs. BigDecimalValue).
Some alternatives also come to my mind based on Saxon's documentation:
atomicValue = new XdmAtomicValue(
new BigDecimalValue(getDoubleValue(fact))
);
or to avoid going through doubles or BigDecimal, something like:
atomicValue = new XdmAtomicValue(
(BigDecimalValue)BigDecimalValue.makeDecimalValue(getStringValue(fact), true)
);
// potentially adding an "instance of BigDecimalValue" check in the middle
// or bypassing all checks with 'false' instead of 'true'
Note: I am not sure I fully understand the issue that arises in other rules if an xs:double is passed instead of an xs:decimal. I suspect that there may be some casting back to xs:string involved in these other rules, as this is where an E could be introduced. XPath comparisons between numeric values of any types should be seamless.
In general (but I am only guessing here as I do not know the details involved, apart from seeing usage of EBA's interval arithmetic functions in the rule), I think it is probably a nice idea to align the types used in or passed to XBRL Formula rules with the original XBRL concept types (use xs:decimal for xbrli:decimalItemType (r) or xbrli:monetaryItemType (m), but xs:double for xbrli:doubleItemType, etc), as the lexical spaces will then match those used in the XBRL instances.

Why does `%4.` add space to my number?

I have this code:
private String padWithZeroRightToPeriod(String serverFormat, float unformattedNumber, int index) {
int nDigits = getNumberOfDigitsAfterPeriod(serverFormat);
String floatingFormat = "%4." + nDigits + "f";
String formattedPrice = String.format(floatingFormat, unformattedNumber);
When called with unformattedNumber being 846, why is the result " 846" (a space and then the three digits)?
What does the %4. mean?
The docs for String.format refer you to this documentation on format strings, which says:
The format specifiers for general, character, and numeric types have the following syntax:
%[argument_index$][flags][width][.precision]conversion
The optional argument_index is a decimal integer indicating the position of the argument in the argument list. The first argument is referenced by "1$", the second by "2$", etc.
The optional flags is a set of characters that modify the output format. The set of valid flags depends on the conversion.
The optional width is a positive decimal integer indicating the minimum number of characters to be written to the output.
The optional precision is a non-negative decimal integer usually used to restrict the number of characters. The specific behavior depends on the conversion.
The required conversion is a character indicating how the argument should be formatted. The set of valid conversions for a given argument depends on the argument's data type.
From your example output, it appears that getNumberOfDigitsAfterPeriod is returing 0, so your format string is %4.0f. So:
It doesn't have an argument index (there's no $ after the 4)
It has a width (4)
It has a precision (0)
And of course it has a conversion (f)
So 846 is output as " 846" because the width is 4. The width in question is the total number of characters output. Here's a different example: Live Copy
public class Example {
public static void main(String args[]) {
System.out.println(String.format("%8.2f", 846.0));
System.out.println(String.format("%8.2f", 42.4));
}
}
Output:
846.00
42.40
Note that each of those is eight characters long.

Converting non-numeric String to Integer?

How can I convert a non-numeric String to an Integer?
I got for instance:
String unique = "FUBAR";
What's a good way to represent the String as an Integer with no collisions e.g. "FUBAR" should always be represented as the same number and shan't collide with any other String. For instance, String a = "A"; should be represented as the Integer 1 and so on, but what is a method that does this (preferrably for all unicode strings, but in my case ASCII values could be sufficient).
This is impossible. Think about it, an Integer can only be 32 bits. So, by the pigeonhole principle, there must exist at least two strings that have the same Integer value no matter what technique you use for conversion. In reality, there are infinite with the same values...
If you're just looking for an efficient mapping, then I suggest that you just use the int returned by hashCode(), which for reference is actually 31 bits.
You can map Strings to unique IDs using table. There is not way to do this generically.
final Map<String, Integer> map = new HashMap<>();
public int idFor(String s) {
Integer id = map.get(s);
if (id == null)
map.put(s, id = map.size());
return id;
}
Note: having unique id's doesn't guarantee no collisions in a hash collection.
http://vanillajava.blogspot.co.uk/2013/10/unique-hashcodes-is-not-enough-to-avoid.html
If you know the character set used in your strings, then you can think of the string as number with base other than 10. For example, hexadecimal numbers contain letters from A to F.
Therefore, if you know that your strings only contain letters from an 8-bit character set, you can treat the string as a 256-base number. In pseudo code this would be:
number n;
for each letter in string
n = 256 * n + (letter's position in character set)
If your character set contains 65535 characters, then just multiply 'n' with that number on each step. But beware, the 32 bits of an integer will be easily overflown. You probably need to use a type that can hold a larger number.
private BigDecimal createBigDecimalFromString(String data)
{
BigDecimal value = BigDecimal.ZERO;
try
{
byte[] tmp = data.getBytes("UTF-8");
int numBytes = tmp.length;
for(int i = numBytes - 1; i >= 0; i--)
{
BigDecimal exponent = new BigDecimal(256).pow(i);
value = value.add(exponent.multiply(new BigDecimal(tmp[i])));
}
}
catch (UnsupportedEncodingException e)
{
}
return value;
}
Maybe a little bit late, but I'm going to give my 10 cents to simplify it (internally is similar to BigDecimal suggested by #Romain Hippeau)
public static BigInteger getNumberId(final String value) {
return new BigInteger(value.getBytes(Charset.availableCharsets().get("UTF-8")));
}
Regardless of the accepted answer, it is possible to represent any String as an Integer by computing that String's Gödelnumber, which is a unique product of prime numbers for every possible String. With that being said it's quite impractical and slow to implement, also for most Strings you would need a BigInteger rather than a normal Integer and to decode a Gödelnumber into its corresponding String you need to have a defined Charset.

convert a hex string to a binary string in byte throws NumberFormatException

public static byte[][] keyArray = new byte[4][4];
String hex = "93";
String hexInBinary = Integer.toBinaryString(Integer.parseInt(hex, 16));
keyArray[row][col] = Byte.parseByte(hexInBinary,2); //this line causes the error
This is the error message I get,
"Exception in thread "main" java.lang.NumberFormatException: Value out of range. Value:"10010011" Radix:2."
I don't want to use getBytes(), because I actually have a long string, "0A935D11496532BC1004865ABDCA42950." I want to read 2 hex at a time and convert to byte.
EDIT:
how I fixed it:
String hexInBinary = String.format("%8s", Integer.toBinaryString(Integer.parseInt(hex, 16))).replace(' ', '0');
keyArray[row][col] = (byte)Integer.parseInt(hexInBinary, 2);
As it is written in the exception message the string you are trying to convert to byte exceeds the max. value of a byte can have.
In your example the string "10010011" equals to 147, but the max value for a byte variable is 2^7 - 1 = 127.
You might want to check the Byte Class documentation;
http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Byte.html#MAX_VALUE
So i suggest to use Integer.parseInt(), instead of parseByte method and then cast the int value to byte, integer value 147 will become -109 when you cast it to byte value.
public class ByteConvert {
public static void main(String[] argv) {
String hex = "93";
String hexInBinary = Integer.toBinaryString(Integer.parseInt(hex, 16));
int intResult = Integer.parseInt(hexInBinary,2);
System.out.println("intResult = " + intResult);
byte byteResult = (byte) (Integer.parseInt(hexInBinary,2));
System.out.println("byteResult = " + byteResult);
byte result = Byte.parseByte(hexInBinary,2);
System.out.println("result = " + result);
}
}
C:\JavaTools>java ByteConvert
intResult = 147
byteResult = -109
Exception in thread "main" java.lang.NumberFormatException: Value out of range.
Value:"10010011" Radix:2
at java.lang.Byte.parseByte(Unknown Source)
at ByteConvert.main(ByteConvert.java:9)
As can be seen, parseByte detects a value "larger" than a byte.
According to the java documention at http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Byte.html#parseByte(java.lang.String),
"The characters in the string must all be digits, of the specified radix
(as determined by whether Character.digit(char, int) returns a nonnegative
value) except that the first character may be an ASCII minus
sign '-' ('\u002D') to indicate a negative value."
So the binary representation is not twos-compliment. The byte 10010011 in twos-compliment notation would be negative given that the upper bit is a 1. So if you want to get the same value as the twos-compliment byte 10010011, you would need to do Byte.parseByte("-1101100");.
Put another way, the maximum value an unsigned byte can have is 255. The maximum value a signed byte can have is 127 (because if the most-significant-bit is 1, then it is interpreted as a negative number). However, the issue with parseByte() is that it instead uses an explicit "-" symbol instead of a 1 to indicate negative numbers. This means that the rest of the "byte" can only use 7 bits.

Categories

Resources