What is the wrong with this code? - java

String phrase = "4556.44";
Float num = new Float(phrase);
int dollars = (int) Math.floor(num);
System.out.println(""+dollars);
int cent = (int) Math.floor((num - dollars) * 100.0F);
int cent2 = (int) ((num - dollars) * 100.0);
System.out.println(""+cent+":"+cent2);
This is a Number to Word Class Code Phrase, My Problem is when I run this code fragment the output result is 4556.43. But the input value is 4556.44. Please tell me why this is happened and I need the answer for correct this Problem.

For high precision calculations with controlled rounding use BigDecimal instead Float

Floats are less precise than doubles which are less precise than BigDecimal.
When working with programmes that absolutely must be precise (like financial applications) use a BigDecimal.
If this is a small homework and non-critical app you can try out Double to see if it is precise enough for you.

int cent = (int)(num * 100f % 100f);

Float is not a good choice for precision calculations.
int cent = (int) Math.floor((num - dollars) * 100.0F);
above statement in the code doesn't exactly give you precise answers as you would expect.
Try using Double or BigInteger if possible.

Floats and Doubles cannot represent all possible real numbers, since they use a specification that makes up numbers by adding any of the following numbers: 1, 1/2, 1/4, 1/8, 1/16 etc...
If you try out 0.1f+0.1f+0.1f==0.3f you'll get false. So, as other people said, use BigDecimal, it uses a different representation, it's much slower, but it won't incur in these problems.

You can also do the following
String phrase = "4556.44";
long money = Math.round(Double.parseDouble(phrase) * 100);
long dollars = money / 100;
long cents = money % 100;
System.out.printf("%,d dollars and %d cents%n", dollars, cents);
prints
4,556 dollars and 44 cents

Related

Sine approximation error in Java

I'm a bit annoyed with a method I wrote to approximate sine function in Java. Here it is, it's based on Taylor's series.
static double PI = 3.14159265358979323846;
static double eps = 0.0000000000000000001;
static void sin(double x) {
x = x % (2 * PI);
double term = 1.0;
double res = 0.0;
for (int i = 1; term > eps; i++) {
term = term * (x / i);
if (i % 4 == 1) res += term;
if (i % 4 == 3) res -= term;
}
System.out.println(sum);
}
For little values, I got very good approximation of sine, but for large values (e.g pow(10,22)), results seems very very wrong.
Here are the results :
sin(pow(10,22)) // 0.8740280612007599
Math.sin(pow(10,22)) // -0.8522008497671888
Does someone have an idea ? Thank you !
Best regards,
Be reassured that the Java sin function will be off too.
You problem is that the Taylor expansion for sin has a small radius of convergence and convergence is slow even if you're within that radius.
There are floating point considerations too: a floating point double gives you about 15 significant figures of accuracy.
So for large arguments for sin, the accuracy will deteriorate significantly especially given that sin is a periodic function:
sin(x + 2 * pi * n) = sin(x) for any integer n.
Your answer is incorrect for big numbers because you accumulate a lot of rounding errors due to double presentation. When the number is big, then your for loop will iterate a lot before the term becomes smaller than epsilon. In each iteration, a rounding error is accumulated. The result is a very big error in the final value. Read some nice reference on "Numerical Analysis". Anyway, Tylor's series approximate sin near 0, by definition. So, it is normal not to be correct for very big numbers.
The difference actually has nothing to do with the radius of convergence of the Taylor Series and has to do with double precision not being accurate enough to hold the precision required for such big numbers. The radius of the Taylor series for the sine function is infinity.
10^22 is approximately 2^73. Since the mantissa for a double precision number is 52 bits, consecutive values that can be stored with double precision format will be 2^21 apart from each other. Since an evaluation of the sine function requires more resolution than that, you won't be able to reliably get an answer.

How can I show up to 2 decimal places without rounding off?

I want to take two decimal places only for a float without rounding off. eg. 4.21777 should be 4.21 and not 4.22. How do I do this?
A simple answer:
double x = 4.21777;
double y = Math.floor(x * 100) / 100;
Subtract 0.005 and then round. For example if you just want to print the number you can use a format of %f6.2 and the value x-0.005.
float f = 4.21777 * 100;
int solution = (int)f;
f = solution/100;
This should work ;)
Explanation: By multiplying with 100, you will get 421.777, which, castet to int, is being rounded down to 421. Now divided by 100 returns its actual value.

Java - How to get the double from an Integer (Money)

I got:
int number = 1255; -> //It could also be 125(1€25Cent) or 10(10Cent) or 5(5Cent)
public double toMoney(int number)
{
...
}
as return, I want the double number: 12.55 or if input: 10 then: 00.10
I know that I can do with Modulo something like this:
1255 % 100.. to get 55.. But how to do it for 12 and at the end, how to
form it as a double?
That method should not exist, because it cannot give correct results.
Because internally, double is a format (binary floating-point) that cannot accurately represent a number like 0.1, 0.2 or 0.3 at all. Read the Floating-Point Guide for more information.
If you need decimals, your output format should be BigDecimal or String.
The way printing money amounts should be done is by using NumberFormat class!
Check out this example:
NumberFormat format = NumberFormat.getCurrencyInstance(Locale.FRANCE);
format.setCurrency(Currency.getInstance("EUR"));
System.out.println( format.format(13234.34) );
Which print this output:
13 234,34 €
You can try different locales and currency codes. See docs: http://download.oracle.com/javase/1.4.2/docs/api/java/text/NumberFormat.html.
If I'm understanding your question correctly, you're probably trying to just do this:
return (double)number / 100.;
Though a word of warning: You shouldn't be using floating-point for money due to round-off issues.
If you just want to print the number in money format, here's a 100% safe method:
System.out.print((number / 100) + ".");
int cents = number % 100;
if (cents < 10)
System.out.print("0");
System.out.println(cents);
This can probably be simplified a lot better... Of course you can go with BigDecimal, but IMO that's smashing an ant with a sledgehammer.
public double toMoney(int number)
{
return number / 100.0;
}
If you're dealing with monetary amounts, do bear in mind that some loss of precision can occur when you convert the number to a double.
public double toMoney(int number)
{
return number / 100.0
}
The trick is to use 100.0 rather than 100 to force java to use double division.
public double toMoney(int number)
{
return number / 100.0;
}
P.S. You shouldn't use double for money values, bad idea.

How to round a number to within a certain range?

I have a value like this:
421.18834
And I have to round it mathematical correctly with a mask which can look like this:
0.05
0.04
0.1
For example, if the mask is 0.04, i have to get the value 421.20, because .18 is nearer at .20 than .16.
All functions that I found using Google didn't work.
Can you please help me?
double initial = 421.18834;
double range = 0.04;
int factor = Math.round(initial / range); // 10530 - will round to correct value
double result = factor * range; // 421.20
You don't need a special function. You multiply your original number by (1/mask), you round it to a decimal and you divide again by the same factor.
Example with 0.05
factor = 1/0.05 = 20
421.18834 * 20 = 8423.7668
int( 8423.7668 ) = 8424
8424.0 / 20.0 = 421.20
Example with 0.01
factor = 1/0.1 = 10
421.18834 * 10 = 4211.8834
int( 4211.8834 ) = 4212
4212.0 / 10.0 = 421.20
Contrary to all the answers you will probably get here about multiplying and dividing, you can't do this accurately because floating point doesn't have decimal places. To need to convert to a decimal radix and then round. BigDecimal does that.
Both fredley and Matteo make the assumption that the rounding factor is itself a factor of 100. For factors like 0.06 or 0.07, this is an incorrect assumption.
Here's my Java routine:
public double rounded(double number, double factor) {
long integer = (long) number;
double fraction = number - integer;
double multiple = (fraction / factor);
multiple = Math.round(multiple);
return factor * multiple + integer;
}

Java using Mod floats

I am working on an exercise in Java. I am supposed to use / and % to extract digits from a number. The number would be something like 1349.9431. The output would be something like:
1349.9431
1349.943
1349.94
1349.9
I know this is a strange way to do but the lab exercise requires it.
Let's think about what you know. Let say you have the number 12345. What's the result of dividing 12345 by 10? What's the result of taking 12345 mod 10?
Now think about 0.12345. What's the result of multiplying that by 10? What's the result of that mod 10?
The key is in those answers.
if x is your number you should be able to do something like x - x%0.1 to get the 1349.9, then x - x%.0.01 to get 1349.94 and so on. I'm not sure though, doing mod on floats is kind of unusual to begin with, but I think it should work that way.
x - x%10 would definetly get you 1340 and x - x%100 = 1300 for sure.
Well the work will be done in background anyway, so why even bother, just print it.
float dv = 1349.9431f;
System.out.printf("%8.3f %8.2f %8.1f", dv, dv, dv);
Alternatively this could be archived with:
float dv = 1349.9431f;
System.out.println(String.format("%8.3f %8.2f %8.1f", dv, dv, dv));
This is a homework question so doing something the way you would actually do in the real world (i.e. using the format method of String as Margus did) isn't allowed. I can see three constraints on any answer given what is contained in your question (if these aren't actually constraints you need to reword your question!)
Must accept a float as an input (and, if possible, use floats exclusively)
Must use the remainder (%) and division (/) operator
Input float must be able to have four digits before and after the decimal point and still give the correct answer.
Constraint 1. is a total pain because you're going to hit your head on floating point precision quite easily if you have to use a number with four digits before and after the decimal point.
float inputNumber = 1234.5678f;
System.out.println(inputNumber % 0.1);
prints "0.06774902343743147"
casting the input float to a double casuses more headaches:
float one = 1234.5678f;
double two = (double) one;
prints "1234.5677490234375" (note: rounding off the answer will get you 1234.5677, which != 1234.5678)
To be honest, this had me really stumped, I spent way too much time trying to figure out how to get around the precision issue. I couldn't find a way to make this program work for 1234.5678f, but it does work for the asker's value of 1349.9431f.
float input = 1349.9431f;
float inputCopy = input;
int numberOfDecimalPoints = 0;
while(inputCopy != (int) inputCopy)
{
inputCopy = inputCopy * 10;
numberOfDecimalPoints++;
}
double inputDouble = (double) input;
double test = inputDouble * Math.pow(10, numberOfDecimalPoints);
long inputLong = Math.round(test);
System.out.println(input);
for(int divisor = 10; divisor < Math.pow(10, numberOfDecimalPoints); divisor = divisor * 10)
{
long printMe = inputLong - (inputLong % divisor);
System.out.println(printMe / Math.pow(10, numberOfDecimalPoints));
}
Of my three constraints, I've satisfied 1 (kind of), 2 but not 3 as it is highly value-dependent.
I'm very interested to see what other SO people can come up with. If the asker has parsed the instructions correctly, it's a very poor exercise, IMO.

Categories