Objective C: Creating Long Double uses Decimal Method

747 views Asked by At

How do I create the following method?

  • I have tried to use modf(n, 1) or modf(n, 2) but those both return an error of "Passing argument 2 of modf makes pointer from integer without a cast.

Heres the method:

(BOOL) numberHasDecimal: (long double) n {
    if (?????) // has decimal, like 16.300000 or 6453.353259
        return YES;
    else
        return NO; // has no decimal, like 58.000000 or 9274.000000
}
4

There are 4 answers

6
Jonathan Grynspan On BEST ANSWER
if (fabsl(fmodl(n, 1.0)) > 0.0) {
    // Has a decimal.
} else {
    // Is an integer.
}

Keep in mind that floating point values are internally rounded in counter-intuitive ways, so a number may have a very small fractional component and still appear integral when passed through fmodl().

Also note that Apple's implementation of Objective-C is broken when handling long double values, and may manifest difficult-to-track errors when you use them.

0
michaellindahl On

Another choice, don't know which to choose from, but probably not this one.

-(BOOL) numberHasDecimal: (long double) n {
    NSMutableString *decimalTempString;
    decimalTempString = [NSMutableString stringWithFormat: @"%Lf", n];

    // while last character of string = 0 delete last character  (1232.10000)
    while ([decimalTempString characterAtIndex:([decimalTempString length] -1)] == '0') {
        NSRange range = {([decimalTempString length] -1), 1};
        [decimalTempString deleteCharactersInRange:range];
    }
    // if last character is . then delete that too  (1232.)
    if ([decimalTempString characterAtIndex:([decimalTempString length] -1)] == '.') {
        return NO; // has no decimal, like 58. or 9274.
    } else {
        return YES; // has decimal, like 16.3 or 6453.353259
    }
1
Dave DeLong On
- (BOOL) numberHasDecimal:(long double)l {
  return (floorl(l) != l);
}
0
ipmcc On

As other posters have indicated, a better question might be to define what "not having a decimal part" means. (Also, I echo their cautions on long doubles.) Which definition is right depends on what you're trying to achieve. I find that "within 1e-6" is often a good definition, but it depends on the situation.

For your specific question, you probably want this:

-(BOOL) numberHasDecimal: (double) n 
{
    double integerPart = 0.;
    if (fabs(modf(n, &integerPart)) > 0.) // has decimal, like 16.300000 or 6453.353259
        return YES;
    else
        return NO; // has no decimal, like 58.000000 or 9274.000000
}

What's going on is that the modf function wants to return the fractional part and store the integer part of the number into another double, the address of which you pass into it. Despite its name, it is not the equivalent of "x % y"; it's really more the equivalent of "return x % 1.0, also storing (x - floor(x)) into the provided pointer" (at least for positive numbers, that is.)

You can think of the second, pointer parameter as a way to return more than one value from a single function call. Even though you don't care, in this case, about the integer part, passing an address for modf to write the integer part into will quiet the compiler and get you the result you're looking for.