views:

80

answers:

4

Hi,

i want to floor a double by its decimal place with variable decimal length (in iphone sdk).

here some examples to show you what i mean

NSLog(@"%f",[self floorMyNumber:34.52462 toPlace:2); // should return 34.52
NSLog(@"%f",[self floorMyNumber:34.52662 toPlace:2); // should return 34.52

NSLog(@"%f",[self floorMyNumber:34.52432 toPlace:3); // should return 34.524
NSLog(@"%f",[self floorMyNumber:34.52462 toPlace:3); // should return 34.524

NSLog(@"%f",[self floorMyNumber:34.12462 toPlace:0); // should return 34.0
NSLog(@"%f",[self floorMyNumber:34.92462 toPlace:0); // should return 34.0

any ideas how to do this?

solution

-(double)floorNumberByDecimalPlace:(float)number place:(int)place {
    return (double)((unsigned int)(number * (double)pow(10.0,(double)place))) / (double)pow(10.0,(double)place);
}
A: 

If you're just rounding them for the purpose of printing them, you do this with the standard printf format specifiers. For example, instead of "%f", to print 3 decimals you could use "%.3f"

arsenm
no i mean "floor". "%.3f" will result 34.525 with a number like 34.5246, not 34.524
choise
+1  A: 

Another solution:

placed is 10 (Example: 13.1), 100 (Example: 12.31) and so on

double value = (double)((unsigned int)(value * (double)placed)) / (double)placed

Quonux
this really looks scary. but check my edit above, it worked like a charm. thanks!
choise
Casting to `unsigned int` will result in all negative values becoming really large positive values, and large valid doubles overflowing. Buyer beware.
rpetrich
Couldn't you do `double value = floor(value * (double)placed) / (double)placed;` instead of risking what rpetrich mentioned?
Wevah
@Wevah looks like your version is working. can you explain the different?
choise
The only real difference is that it avoids the `unsigned int` cast, and thus avoids the overflow issues with negative values and really large values (i.e., values greater than `UINT_MAX`).
Wevah
A: 

Use sprintf (or better snprintf) to format it to a string then crop the end of the string.

R..
A: 

Multiply it by 10^(decimal places), cast it to an integer, then divide it by 10^(decimal places).

double floorToPlace(double number, int places)
{
    int decimalPlaces = 1;
    for (int i = 0; i < places; i++) divideBy *= 10;

    return (int)(number * decimalPlaces) / (double)decimalPlaces;
}
zneak
thanks, but quonux was a little bit faster ;)
choise
Yeah. It's okay. No hurt feelings.
zneak