NSNumber from CGFloat
Asked Answered
F

2

11

Is there a safe way to "convert" a CGFloat to a NSNumber ?

NSNumber has the numberWithFloat: and numberWithDouble: methods but CGFloat being defined as float or double depending on the platform, it seems risky to use either one of them.

Or is numberWithDouble: safe to use with a CGFloat, as it is the one with the more precision ?

Fafnir answered 12/6, 2013 at 14:9 Comment(11)
If you have a enough high compiler version, just write @(myNumber) and it will be resolved at compile time. However you can safely call [NSNumber numberWithDouble: myNumber], if CGFloat is defined to be double you do it correctly, it CGFloat is defined to be float you still haven't lost any precision.Microelectronics
safe? can you explain?Barmecide
safe as "without precision loss". Is this why I was downvoted ?Fafnir
I down voted it because IMHO you are just over thinking. C is full of functions that handle doubles, not overridden to work also with floats just because if you pass a float instead of a double nothing harmful can happen. It will just be implicitly casted to a double, which uses extra precision.Microelectronics
I'm over thinking it because my code will handle real money. So better be safe (pun not intended) than sorry. (and I also don't think this was worth a downvote, but eh...)Fafnir
This casting wastes cycles, and can be significant in code that does lots of floating point arithmetic. In terms of math functions, I recommend using tgmath.h and letting the compiler choose the right function for you at compile time.Bursary
If you're handling money, you may wish to consider using a fixed point or decimal representation. See NSDecimal and NSDecimalNumber.Bursary
For which device support you are bulding this app?Barmecide
Don't use floating point for real money.Neuropath
@LithuT.V iPad but I didn't want it to be relevant, I wanted portable-ish code. @Bursary already using these, but wanted a convenient way to init them from CGFloat.Fafnir
well iphone is a 32 bit device .CGFloat is a regular float on 32-bit systems and a double on 64-bit systems.thats why i askedBarmecide
B
34

I believe @ NSNumber literal is good enough

@(myCGFloat)

Read more here: http://clang.llvm.org/docs/ObjectiveCLiterals.html

Balustrade answered 12/6, 2013 at 14:22 Comment(1)
Thanks for the solution and the link. This was enlightening :)Fafnir
B
24

This is how I handled it:

@interface NSNumber (CGFloatAdditions)

+ (NSNumber*)numberWithCGFloat: (CGFloat)value;
- (CGFloat)CGFloatValue;

@end

@implementation NSNumber (CGFloatAdditions)

+ (NSNumber*)numberWithCGFloat: (CGFloat)value
{
#if CGFLOAT_IS_DOUBLE
    return [NSNumber numberWithDouble: (double)value];
#else
    return [NSNumber numberWithFloat: value];
#endif
}

- (CGFloat)CGFloatValue
{
#if CGFLOAT_IS_DOUBLE
    return [self doubleValue];
#else
    return [self floatValue];
#endif
}


@end

CGFLOAT_IS_DOUBLE is defined in CGBase.h conditionally by platform.

Bursary answered 12/6, 2013 at 14:17 Comment(4)
This is not even necessary, it's over-coding. If you call [NSNumber numberWithDouble: value] (for compiler versions that don't support literal numbers) you don't risk to lose any precision whether if the number is float or double.Microelectronics
Yes, but you waste cycles to convert between float and double on platforms where CGFloat is a float. But whatever. Use this, don't use this. I wrote it a long time ago and I continue to use it. It works for me.Bursary
Thnaks @ipmcc, I'll use Lukas' solution but yours is what I was searching for originally.Fafnir
I find it odd this is not NSNumber already, since they did add methods for NSInteger.Atreus

© 2022 - 2024 — McMap. All rights reserved.