Objective-C: Flooring to 3 decimals correctly

好久不见. 提交于 2019-12-02 04:51:06

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!