Valhalla Legends Forums Archive | Java Programming | My rounding function. Need constructive criticism please.

AuthorMessageTime
bethra
Ok, so my assignment is to:
[quote]
Write and test a method round that has a real parameter amount and an integer parameter n and that returns the value of amount rounded to n places.  Fore example, round(10.536, 0), round(10.536, 1), and round(10.536, 2) should return the values 11.0, 10.5, 10.54, respectively.
[/quote]

I wrote my function, tested it, and it works.  However, the way I do it is probably messy and not the best way I'm guessing.  So, I'd like some constructive criticism so that I can improve my algorithm.

Here is the code:
[code]
public class Round{
public static double round(double amount, int n)
{
if(n == 0){
return (double)Math.round(amount);
}else{
double fracPart = (amount % 1);
double intPart = (amount - fracPart);

double decPlace = (amount / (1 / Math.pow(10, n + 1))) % 10;

if((int)decPlace >= 5)
{
fracPart += (1 / Math.pow(10, n));
}

int rPart = (int)(fracPart * (1 / Math.pow(10, -n)));

return intPart + ((double)rPart * (1 / Math.pow(10, n)));
}
}

public static void main(String[] args)
{
double num = 10.536;

for(int i = 0; i < 3; ++i)
{
System.out.println(num + " rounded to " + i + " decimal places:");
System.out.println(round(num, i) + "\n");
}
}
}
[/code]

Here is the output:
[quote]
10.536 rounded to 0 decimal places:
11.0

10.536 rounded to 1 decimal places:
10.5

10.536 rounded to 2 decimal places:
10.54
[/quote]


Thanks.
November 21, 2005, 8:09 PM
iago
I would do:

Math.floor(amount * ((double) 10[sup]n[/sup])) / (double) 10[sup]n[/sup]

I believe that would get you the same answer, faster. 

BUGS: Mine rounds down.  To round up, you'd probably use Math.round() or something.  I'm not entirely positive what the function is, so I didn't use it :)
November 21, 2005, 11:13 PM
Ender
[quote author=Sorc.Polgara link=topic=13313.msg134916#msg134916 date=1132603780]
Here is the output:
10.536 rounded to 0 decimal places:
11.0
[/quote]

It should be 11. You may have to convert a double to an int. It can be done easily using a wrapper class, either a Double or an Integer.

You have some extraneous parentheses. Like these lines for example:
[quote]
double fracPart = (amount % 1);
double intPart = (amount - fracPart);
[/quote]

November 22, 2005, 1:04 AM
kamakazie
Here is what I came up with:

[code]
public static double round(double amount, int n)
{
return ((int)(amount * Math.pow(10, n) + 0.5) / Math.pow(10, n));
}
[/code]

Seems to work.
November 22, 2005, 1:48 AM
bethra
[quote author=dxoigmn link=topic=13313.msg134966#msg134966 date=1132624105]
Here is what I came up with:

[code]
public static double round(double amount, int n)
{
return ((int)(amount * Math.pow(10, n) + 0.5) / Math.pow(10, n));
}
[/code]

Seems to work.
[/quote]

WOW, that is like freaking 10000000 times shorter.  THANKS.

-------------------------
[quote author=Ender link=topic=13313.msg134962#msg134962 date=1132621474]
[quote author=Sorc.Polgara link=topic=13313.msg134916#msg134916 date=1132603780]
Here is the output:
10.536 rounded to 0 decimal places:
11.0
[/quote]

It should be 11. You may have to convert a double to an int. It can be done easily using a wrapper class, either a Double or an Integer.

You have some extraneous parentheses. Like these lines for example:
[quote]
double fracPart = (amount % 1);
double intPart = (amount - fracPart);
[/quote]
[/quote]

[quote]
Write and test a method round that has a real parameter amount and an integer parameter n and that returns the value of amount rounded to n places.  For example, round(10.536, 0), round(10.536, 1), and round(10.536, 2) should return the values [size=4]11.0[/size], 10.5, 10.54, respectively.
[/quote]
Yeah, I have a habit of putting extraneous parentheses... hehe.

Ummm, the method is suppose to return a double.  So returning 11.0 is suppose to be correct


EDIT:  Wait, I see where you are getting that it should be 11
[quote]
... returns the value of amount rounded to n places.
[/quote]
Since it would be rounded to 0 decimal places, then it would really be an integer.

Well, since the example he gives in the assignment gives the result as 11.0, I'm going to stick with just returning values that have 0 decimal places as doubles.
November 22, 2005, 2:34 AM
kamakazie
[quote author=Sorc.Polgara link=topic=13313.msg134971#msg134971 date=1132626860]
WOW, that is like freaking 10000000 times shorter.  THANKS.
[/quote]

Do you understand why it works, though? Uses the same method that Math.round()'s internal implementation uses, kind of. Might be better to use Math.floor() instead of casting to an int.

Edit: Haha i just noticed it looks a lot like Iago's. When I had initially wrote that function is was pretty hideous looking until I noticed it could be simplified.
November 22, 2005, 2:54 AM
Ender
[quote]Ummm, the method is suppose to return a double.  So returning 11.0 is suppose to be correct[/quote]
Yeah, but mathematically it isn't correct, as it implies that 11.01 rounded to one decimal place is the same as 11.1 rounded to 0 decimal places. You wouldn't return an integer in that method of course, but you could call another function that converts a double into an int and return that int.
And this function should be private, since the end-user will never use it.

You could also do this completely excluding the Math class. The algorithm could be:
~input n, the decimal places to round to
~break double into integer part I and fraction part F
~take the fraction part, multiply it by 10^n,  break it up into integer part I2 and fraction part F2, if fraction part is greater than 0.5, then integer part ++
~return (double) (first integer part (I) + second integer part (I2) x 10^-n)                // note pemdas / order of operations

I believe this will work but I haven't tested it.

Another fun way to do it without the Math class would be to write a class that performs bitwise operations / logical gates on base 10 to isolate certain digits/decimal places
November 22, 2005, 2:56 AM
bethra
[quote author=dxoigmn link=topic=13313.msg134976#msg134976 date=1132628096]
[quote author=Sorc.Polgara link=topic=13313.msg134971#msg134971 date=1132626860]
WOW, that is like freaking 10000000 times shorter.  THANKS.
[/quote]

Do you understand why it works, though? Uses the same method that Math.round()'s internal implementation uses, kind of. Might be better to use Math.floor() instead of casting to an int.

Edit: Haha i just noticed it looks a lot like iago's. When I had initially wrote that function is was pretty hideous looking until I noticed it could be simplified.
[/quote]

Yes, actually, what I did is wrote this huge comment block so that when my professor reads my code he won't mark off for not having documentation.

Here it is:
[code]
/* round():  Rounds a given real number to a given number places.
* and returns the rounded value as type double.
*/
public static double round(double amount, int n)
{
return ((int)(amount * Math.pow(10, n) + 0.5) / Math.pow(10, n));

/* A simplified version of the code above:
*    ( (int)( (amount * 10^n) + 0.5 ) ) / ( 10^n )
*
* A step-by-step explanation of the above algorithm.
* 1.  Moves the decimal point to the right n places by simply
*    multiplying the amount by 10 to the nth power.  Doing
*    this allows easy evalution of the decimal place that is
*    to be rounded.
* 2.  Adds 0.5 (one half) to the tenths place of the resulting
*    value in step 1, which is the decimal place that must be
*    evaluated in order to round.  Adding 0.5 rounds the number
*    and will increment accordingly if the value of the digit
*    in the tenths place is greater than or equal to 0.5.
* 3.  The value that is computed in steps 1 and 2 is converted
*    to integer type by typcasting.
* 4.  The resulting integer from steps 1, 2, and 3 is divided by
*    10 to the nth power.
*    <NOTE: The method Math.pow(double a, double b) computes
*    the value of a to the b power and returns it as type
*    double.  Thus, an integer is being divided by a double.
*    Therefore the resulting quotient is then of double type.>
* 5.  Returns the amount rounded to n decimal places as double
*    type.
*/
}
[/code]
November 22, 2005, 4:59 AM
kamakazie
Haha, that is one huge comment for 1 line of code. But I guess it is needed.
November 22, 2005, 5:05 AM
bethra
[quote author=Ender link=topic=13313.msg134977#msg134977 date=1132628199]
[quote]Ummm, the method is suppose to return a double.  So returning 11.0 is suppose to be correct[/quote]
Yeah, but mathematically it isn't correct, as it implies that 11.01 rounded to one decimal place is the same as 11.1 rounded to 0 decimal places.
[/quote]

Your right.  I think I'm going to fix it and then correct the professor because his example is mathematically incorrect.  If he takes off for it I'm going to be pissed, I should even go to the other CS Professors and explain it if he does!

I don't think my professor even has a Ph.D. in Computer Science, only Mathematics.  He should know better!
November 22, 2005, 5:12 AM
bethra
[quote author=iago link=topic=13313.msg134946#msg134946 date=1132614808]
I would do:

Math.floor(amount * ((double) 10[sup]n[/sup])) / (double) 10[sup]n[/sup]

I believe that would get you the same answer, faster. 

BUGS: Mine rounds down.  To round up, you'd probably use Math.round() or something.  I'm not entirely positive what the function is, so I didn't use it :)

[/quote]

I was curious and decided to try and fix iago's code, which doesn't quite work as he mentioned.  Thanks to dxoigmn's code I was able to easily fix it.

Working code:
[code]
/* round():  Rounds a given real number to a given number places.
* and returns the rounded value as type double.
*/
public static double round(double amount, int n)
{
return Math.floor(amount * Math.pow(10, n) + 0.5) / Math.pow(10, n);
}[/code]

NOTE:  Adding 0.5 fixed the rounding problem quite nicely.
November 22, 2005, 5:35 AM
bethra
[quote author=Ender link=topic=13313.msg134977#msg134977 date=1132628199]
[quote]Ummm, the method is suppose to return a double.  So returning 11.0 is suppose to be correct[/quote]
Yeah, but mathematically it isn't correct, as it implies that 11.01 rounded to one decimal place is the same as 11.1 rounded to 0 decimal places. You wouldn't return an integer in that method of course, but you could call another function that converts a double into an int and return that int.
And this function should be private, since the end-user will never use it.

You could also do this completely excluding the Math class. The algorithm could be:
~input n, the decimal places to round to
~break double into integer part I and fraction part F
~take the fraction part, multiply it by 10^n,  break it up into integer part I2 and fraction part F2, if fraction part is greater than 0.5, then integer part ++
~return (double) (first integer part (I) + second integer part (I2) x 10^-n)                // note pemdas / order of operations

I believe this will work but I haven't tested it.
[/quote]

I'm procrastinating studying so tried your solution out, it works as you thought.  However I use the Math.pow() function. 

Here is the code:
[code]
// Rounds a real number to n decimal places and returns the
// rounded value as a double
public static double round(double amount, int n)
{
if(n == 0){
return (double)Math.round(amount);
}else{
// Break amount into integer part1 (I1) and a fraction part1 (F1)
double F1 = amount % 1;
int I1 = (int)(amount - F1);

// Multiply the fraction part1 (F1) by 10^n, store it to amount2
double amount2 = F1 * Math.pow(10, n);

// Break amount2 into integer part2 (I2) and fraction part2 (F2)
double F2 = amount2 % 1;
int I2 = (int)(amount2 - F2);

// If the fraction part2 (F2) is greater than 0.5, then increment
// integer part2 (I2) by 1
if(F2 >= 0.5)
++I2;

// Multiply integer part2 (I2) by 10^-n and add it to integer
// part1, then typecast it as type double and return the value
return (double)(I1 + I2 * Math.pow(10, -n));
}
}
[/code]

I added this if statement that will simply use the Math.round() function if n equals 0... instead of going through all those steps, just use the Math.round() for when n needs to be rounded to 0 decimal places.

It seems to work!  This is a good example of to use to *try* and *explain* in pseudo-like terms to my fellow students how to approach the algorithm.  I will undoubtly be recieving IM's the night before this assignment is due.
November 22, 2005, 6:27 AM
iago
[quote author=Sorc.Polgara link=topic=13313.msg134993#msg134993 date=1132637746]
[quote author=iago link=topic=13313.msg134946#msg134946 date=1132614808]
I would do:

Math.floor(amount * ((double) 10[sup]n[/sup])) / (double) 10[sup]n[/sup]

I believe that would get you the same answer, faster. 

BUGS: Mine rounds down.  To round up, you'd probably use Math.round() or something.  I'm not entirely positive what the function is, so I didn't use it :)

[/quote]

I was curious and decided to try and fix iago's code, which doesn't quite work as he mentioned.  Thanks to dxoigmn's code I was able to easily fix it.

Working code:
[code]
/* round():  Rounds a given real number to a given number places.
* and returns the rounded value as type double.
*/
public static double round(double amount, int n)
{
return Math.floor(amount * Math.pow(10, n) + 0.5) / Math.pow(10, n);
}[/code]

NOTE:  Adding 0.5 fixed the rounding problem quite nicely.
[/quote]

Instead of adding 0.5, using Math.round instead of Math.floor should fix everything. :)
November 22, 2005, 4:50 PM
Ender
[quote author=Ender link=topic=13313.msg134977#msg134977 date=1132628199]
Another fun way to do it without the Math class would be to write a class that performs bitwise operations / logical gates on base 10 to isolate certain digits/decimal places
[/quote]

Hm, I got bored, then realized this was useless, but I post it anyways because I spent a while making the algorithm work... perhaps this could be useful for *something* :(

NOTE: The AND gate does the following:
    T  F
T  T  F
F  F  F

In other words, if both things are true, then it comes out true. For this crude useless base 10 AND, if both things are the same condition (excluding 0, as 0 would mean undefined or w/e) then it comes out as that condition.

[code]
/**
* Useless Base 10 AND operator
*/

/**
* @author Andy
*
*/
public final class DecimalOps {

public DecimalOps(int comparable, int comparison) {
System.out.println("Answer: " + recursAND(comparable, comparison));
System.out.println("This should return 204");
}

public int recursAND(double comparable, double comparison) {
Double doubleWrapper = new Double(recursAND(comparable, comparison, 0.0));
return doubleWrapper.intValue();
}

private double recursAND(double comparable, double comparison, double power) {
if ( (comparable < Math.pow(10, power)) && (comparison < Math.pow(10, power)) )
return 0.0;
else {
double digit = ( (comparable * Math.pow(10, -power -1)) % 1 ) * 10;
        double digit2 = ( (comparison * Math.pow(10, -power -1)) % 1 ) * 10;
       
        digit = digit - (digit % 1);
        digit2 = digit2 - (digit2 % 1);
       
        if (digit == digit2)
        return recursAND(comparable, comparison, power + 1) + digit * Math.pow(10, power);
        else
        return recursAND(comparable, comparison, power + 1); 
}
     
}

/**
* @param args
*/
public static void main(String[] args) {
int comparable = 1234;
int comparison = 3254;
System.out.println(comparable + " compared to " + comparison);
new DecimalOps(comparison, comparable);
}

}
[/code]
[code]
Input: Compare 1234 to 3254
Output: 204
This should return 204
[/code]
November 22, 2005, 11:49 PM
Yoni
The opposite of the floor function is called the ceiling function. The function iago forgot the name of is probably something like Math.ceil.
November 27, 2005, 2:26 AM
Spht
I love you Yoni
November 27, 2005, 3:01 AM
Quarantine
awwwwwww
November 27, 2005, 4:28 AM
iago
[quote author=Yoni link=topic=13313.msg135437#msg135437 date=1133058410]
The opposite of the floor function is called the ceiling function. The function iago forgot the name of is probably something like Math.ceil.
[/quote]
I was looking for the one half way between floor and ceiling, actually.  Like, maybe chest level.  "round"
November 27, 2005, 3:45 PM
JoeTheOdd
[tt](Math.floor(i) + Math.ceil(i)) / 2[/tt]

Chest level.
November 28, 2005, 1:02 PM
iago
[quote author=Joe link=topic=13313.msg135555#msg135555 date=1133182960]
[tt](Math.floor(i) + Math.ceil(i)) / 2[/tt]

Chest level.
[/quote]

If you're planning to use that as an integer, then it will return the same result as Math.floor(i);
November 28, 2005, 1:53 PM
JoeTheOdd
Oh, that's true..

[code]public static double chestLevel(double d) {
  // Double D, haha. I didn't realize that it had such an ambiguous meaning until I typed it. It's staying!
  return (Math.floor(i) + Math.ceil(i)) / 2;
}[/code]

And is Ceiling really a math function, or was Yoni just being humorus? This may sound kinda stupid, but I found that pretty funny. Of course, I found "Fibonacci" to be funny too.

EDIT -
I spent too much time with VB today (an hour, class time). I forgot my semicolon! Pheer.
November 28, 2005, 11:50 PM
iago
[quote author=Joe link=topic=13313.msg135617#msg135617 date=1133221807]
Oh, that's true..

[code]public static double chestLevel(double d) {
  // Double D, haha. I didn't realize that it had such an ambiguous meaning until I typed it. It's staying!
  return (Math.floor(i) + Math.ceil(i)) / 2;
}[/code]

And is Ceiling really a math function, or was Yoni just being humorus? This may sound kinda stupid, but I found that pretty funny. Of course, I found "Fibonacci" to be funny too.

EDIT -
I spent too much time with VB today (an hour, class time). I forgot my semicolon! Pheer.
[/quote]

yes, ceil is a real function, and yes, it's the opposite of floor.  It's around in most real languages that I'm aware of. 
November 29, 2005, 12:12 AM
Yoni
[quote author=iago link=topic=13313.msg135627#msg135627 date=1133223120]
[quote author=Joe link=topic=13313.msg135617#msg135617 date=1133221807]
Oh, that's true..

[code]public static double chestLevel(double d) {
// Double D, haha. I didn't realize that it had such an ambiguous meaning until I typed it. It's staying!
return (Math.floor(i) + Math.ceil(i)) / 2;
}[/code]

And is Ceiling really a math function, or was Yoni just being humorus? This may sound kinda stupid, but I found that pretty funny. Of course, I found "Fibonacci" to be funny too.

EDIT -
I spent too much time with VB today (an hour, class time). I forgot my semicolon! Pheer.
[/quote]

yes, ceil is a real function, and yes, it's the opposite of floor. It's around in most real languages that I'm aware of.

[/quote]
Not just programming languages; it's a common notation in mathematics as well.
http://mathworld.wolfram.com/FloorFunction.html
http://mathworld.wolfram.com/CeilingFunction.html

A short list of things that aren't funny:
1. "ceiling function"
2. "Fibonacci" (listen man, that's a mathematician's last name. Do I say "Joe" is funny?)
3. "double d"
December 3, 2005, 9:30 PM
iago
[quote author=Yoni link=topic=13313.msg136238#msg136238 date=1133645446]
3. "double d"
[/quote]
I'm going to have to disagree with you there..
December 4, 2005, 6:30 AM
Yoni
shhh iago. I'm trying to own Joe.
December 4, 2005, 7:15 PM
Quarantine
LOL.
December 4, 2005, 10:12 PM
bethra
[quote author=iago link=topic=13313.msg136322#msg136322 date=1133677842]
[quote author=Yoni link=topic=13313.msg136238#msg136238 date=1133645446]
3. "double d"
[/quote]
I'm going to have to disagree with you there..
[/quote]
Me too.  lol.
December 7, 2005, 12:02 AM
JoeTheOdd
[quote]2. "Fibonacci" (listen man, that's a mathematician's last name. Do I say "Joe" is funny?)[/quote]

No, but a bunch of people say that LaFrance is funny. =/.
December 7, 2005, 1:14 PM
rabbit
Looking!

HAHAHAHA!!
December 8, 2005, 2:48 AM

Search