问题
I am trying to floor a float value to the third decimal. For example, the value 2.56976 shall be 2.569 not 2.570. I searched and found answers like these:
floor double by decimal place
Such answers are not accurate. For example the code:
double value = (double)((unsigned int)(value * (double)placed)) / (double)placed
can return the value - 1
and this is not correct. The multiplication of value and placed value * (double)placed)
could introduce something like: 2100.999999996. When changed to unsigned int, it becomes 2100 which is wrong (the correct value should be 2101). Other answers suffer from the same issue. In Java, you can use BigDecimal
which saves all that hassels.
(Note: of course, rounding the 2100.9999 is not an option as it ruins the whole idea of flooring to "3 decimals correctly")
回答1:
The following code should work:
#include <stdio.h>
#include <math.h>
int main(void) {
double value = 1.23456;
double val3;
val3 = floor(1000.0 * value + 0.0001) * 0.001; // add 0.0001 to "fix" binary representation problem
printf("val3 is %.8f; the error is %f\n", val3, 1.234 - val3);
}
this prints out
val3 is 1.23400000; the error is 0.000000
If there are any residual errors, it comes about from the fact that floating point numbers cannot necessarily be represented exactly - the idea behind BigDecimal and things like that is to work around that in a very explicit way (for example by representing a number as its digits, rather than a binary representation - it's less efficient, but maintains accuracy)
回答2:
I had to consider a solution involving NSString and it worked like a charm. Here is the full method:
- (float) getFlooredPrice:(float) passedPrice {
NSString *floatPassedPriceString = [NSString stringWithFormat:@"%f", passedPrice];
NSArray *floatArray = [floatPassedPriceString componentsSeparatedByString:@"."];
NSString *fixedPart = [floatArray objectAtIndex:0];
NSString *decimalPart = @"";
if ([floatArray count] > 1) {
NSString *decimalPartWhole = [floatArray objectAtIndex:1];
if (decimalPartWhole.length > 3) {
decimalPart = [decimalPartWhole substringToIndex:3];
} else {
decimalPart = decimalPartWhole;
}
}
NSString *wholeNumber = [NSString stringWithFormat:@"%@.%@", fixedPart, decimalPart];
return [wholeNumber floatValue];
}
回答3:
For example, the value 2.56976 shall be 2.569 not 2.570
Solution is has simple as that :
double result = floor(2.56976 * 1000.0) / 1000.0;
I don't know why you search complication... this works perfectly, doesn't need to pass by some unsigned int
or other + 0.0001
or whatever.
Important note :
NSLog(@"%.4f", myDouble);
Actually do a round on your variable. So it's improper to believe you can floor with a %.Xf
来源:https://stackoverflow.com/questions/17159611/objective-c-flooring-to-3-decimals-correctly