# Converting a numerical string to the equivalent multipled by 100

Method:

• Input: a string which represents an integer or a non-integer value.
• Output: a string which represents the same value multiplied by 100.

Requirements:

• No floating-point unless needed.
• No leading 0s in the part left of the floating-point.
• No trailing 0s in the part right of the floating-point.

I cannot use the Double.parseDouble method, because it sometimes yields an "ugly" result.

For example:

String.valueOf(Double.parseDouble("0.0071")*100)); // yields 0.7100000000000001
String.valueOf(Double.parseDouble("0.072" )*100)); // yields 7.199999999999999


Here is my code, and I would like to know if there are any cavities in it:

String MultiplyBy100(String number)
{
StringBuilder sb = new StringBuilder();

String[] parts = number.split("\\.");
if (parts.length == 1)
sb.append(parts[0]+"00");
else if (parts[1].length() == 1)
sb.append(parts[0]+parts[1]+"0");
else if (parts[1].length() == 2)
sb.append(parts[0]+parts[1]);
else
sb.append(parts[0]+parts[1].substring(0,2)+"."+parts[1].substring(2));

if (sb.charAt(0) == '-')
{
while (sb.length() > 2 && sb.charAt(1) == '0' && sb.charAt(2) != '.')
sb.deleteCharAt(1);
}
else
{
while (sb.length() > 1 && sb.charAt(0) == '0' && sb.charAt(1) != '.')
sb.deleteCharAt(0);
}

return sb.toString();
}

-
If your input is the string '0' will the output be the string '000'? –  trichoplax Mar 20 '14 at 20:51
@githubphagocyte: No, why would it be? –  barak manos Mar 20 '14 at 20:57
My apologies - I see my mistake now. –  trichoplax Mar 20 '14 at 21:02
@palacsint already answered this, but in a nutshell the issue is simply that floating point data types are imprecise and math operations on floats produce rounding errors at the edge of the precision of the data type (turning 0.0071 into 0.007100000000000001 for instance). That is totally fine as long as the error falls outside the precision you require. Decimal data types (scaled integers) on the other hand are not subject to those rounding errors. Math results from decimal types will be as precise as the inputs. Caveat: decimal operations are extremely slow compared to floats. –  Craig Mar 21 '14 at 12:23
Also, my comment that "Math results from decimal types will be as precise as the inputs" was on the simplistic side, but these comment fields are short. The results will be as precise as the least precise of the inputs, and still not always perfect mathematically, and quite slow because the operations are 100% software with no help from specialized hardware. The decimal data type is fundamentally the same thing whether you're dealing with Java, C#, C++, MySQL or SQL Server. This post is informative –  Craig Mar 21 '14 at 12:33

1. It would be much easier with BigDecimals:

String input = "00007.880000";
BigDecimal hundred = BigDecimal.valueOf(100);
BigDecimal result = new BigDecimal(input).multiply(hundred).stripTrailingZeros();

System.out.println(result.toString()); // prints "788"


It works with big numbers well:

String input = "0000123456789123456789.123456789123456789123456789123456789880000";
BigDecimal hundred = BigDecimal.valueOf(100);
BigDecimal result = new BigDecimal(input).multiply(hundred).stripTrailingZeros();

// prints "12345678912345678912.345678912345678912345678912345678988"
System.out.println(result.toString());


2. The original code returns 788.0000 for 00007.880000 which I guess does not fulfill the specification.

3. Java developers usually start method names with lowercase letters.

Methods should be verbs, in mixed case with the first letter lowercase, with the first letter of each internal word capitalized.

-
So much for the answer I was half way through –  rolfl Mar 20 '14 at 12:29
What about 1.234? Will BigDecimal yield 123.4? –  barak manos Mar 20 '14 at 12:31
@barakmanos you should read the documentation and try this. It will help you learn. But, yes, it will. –  rolfl Mar 20 '14 at 12:32
Oh... was probably thinking of BigInteger... –  barak manos Mar 20 '14 at 12:33
Thanks. Regarding your second comment: I assume that the input is already "aligned" with the requirements of the output, so 00007.880000 is not a viable input in my program (though, I should have probably mentioned that in the question). Regarding your third comment: I know, it's just a typo (happened when I copied the code I wanted to be reviewed into a separate method). Thanks again for the detailed answer. –  barak manos Mar 20 '14 at 15:22

Aside from palacsint's great suggestions:

• You are using a StringBuilder, yet you still are doing string concatenations.

• Your code for removing the leading zeros duplicates the for while loop.

Also: Why is your original input a string? This doesn't feel right. I've got the feeling there is something wrong with the bigger picture of your code.

EDIT: I meant the while loops. Better would be something like:

int startAt = sb.charAt(0) == '-' ? 1 : 0;

while (sb.length() > startAt + 1 && sb.charAt(startAt) == '0' && sb.charAt(startAt + 1) != '.')
sb.deleteCharAt(startAt);


boolean negative = sb.charAt(0) == '-';
if (negative) sb.deleteCharAt(0);

while (sb.length() > 1 && sb.charAt(0) == '0' && sb.charAt(1) != '.')
sb.deleteCharAt(0);

if (negative) sb.insert(0, '-');


Thanks. What do you mean by "duplicates the for loop"? First of all, there are no for loops in my question, only while loops. Second, I don't see how they are duplicated. My original input is a String because I read it from a file, and if I read it as Double, then... well, you can guess what might happen... –  barak manos Mar 20 '14 at 15:25