Cgfloat-Based Math Functions

CGFloat-based math functions?

Edit: So this question is no longer theoretical now that we have 64-bit iOS!

I think the easiest way to deal with this is to use tgmath.h, instead of math.h (math.h gets imported by Cocoa automatically, tgmath doesn't so you'll need to declare it somewhere).

There are a number of potential solutions discussed at the Cocoa mailing list thread:
http://www.cocoabuilder.com/archive/cocoa/291802-math-functions-with-cgfloat.html

I would agree with the majority of people on that list that tgmath is probably the way to go. I believe it was originally intended to allow easy porting of Fortran code, but it also works in this scenario. TGMath will let you do:

double floor(double x);
float floor(float x);
long double floor(long double x);

CGFloat: round, floor, abs, and 32/64 bit precision

You may use those functions from tgmath.h.

#include <tgmath.h>

...

double d = 1.5;
double e = floor(d); // will choose the 64-bit version of 'floor'

float f = 1.5f;
float g = floor(f); // will choose the 32-bit version of 'floorf'.

Using CGFloat and memory footprint

Think of it this way. Memory footprint often means how much memory you are consuming at any time. If you without any reason use 64 bit values instead of perfectly useful 32 bit ones, then there is some marginal inflation. That said, I'll bet most of your usage is in automatics and object ivars.

On iOS now, CGFloat == float.

I personally ALWAY use CGFloat for anything that might interface with iOS - that is, unless I'm doing some math functions. And for exactly as you said. The other day I had to grab some code on iOS and move it to a Mac app, and it took almost not time (as I use CGFlat, NSInteger, and friends). You will get no conversion warnings (ie moving 64 bit values into 32 bit ones).

In the future, given the popularity of iOS, its quite likely that there will be processors using 64 bit floating point and integers. Its the nature of progress. If you use the CGFloat and friends, your code will compile without warnings on a universal app the does both 32 and 64 bit.

Replacement for `fabs`, `fmax`, etc. for use with CGFloat on 64-bit iOS devices

There is never any "data loss" incurred when converting a float into a double. That conversion is always exact.

Your solutions 1 & 2 are entirely equivalent semantically, though (2) is more stylistically correct.

Your solution 3 is formally not equivalent; it may incur extra conversions between float and double, which may make it slightly less efficient (but the actual result is identical).

Basically, it doesn't matter, but use tgmath.

How to round CGFloat

There are already standard functions with behaviors you might need in <math.h> such as: floorf, ceilf,
roundf, rintf and nearbyintf (lasf 'f' means "float" version, versions without it are "double" versions).

It is better to use standard methods not only because they are standard, but because they work better in edge cases.

2013 Update (jessedc)

iOS is no longer only 32 bit. There are a number of other answers to this question that are now more relevant.

Most answers mention importing tgmath.h

  • https://stackoverflow.com/a/5352779/184130
  • https://stackoverflow.com/a/7695011/184130

CGFloat floor to NSInteger

Okay, as you mentioned strict compiler settings, I tried again and found the solution.
The compiler warning is because you are trying to cast the floor function to a NSInteger value and not the returned value.

To solve this, all you have to do, is to put floor(width) in parentheses like this:

NSInteger num = (NSInteger) (floor(width));

or save the result of the floor operation to another CGFloat and cast the new variable to NSInteger

CGFloat floored = floor(width);
NSInteger num = (NSInteger) floored;

What is the purpose of CGFloat

typedef float CGFloat;// 32-bit
typedef double CGFloat;// 64-bit

It is for programming with 32/64 bit system. If you use CGFloat, it will auto create a regular float.

You can use Command + double click to get in relative declare file.You may find why iOS offer CGFloat there.

Parse Number Column to CGFloat

NSNumber has already provided options for you to do it.

I suggestion you read on the documentation found here.

excerpt from Apple doc:

NSNumber is a subclass of NSValue that offers a value as any C scalar (numeric) type. It defines a set of methods specifically for setting and accessing the value as a signed or unsigned char, short int, int, long int, long long int, float, or double or as a BOOL.

to answer your question.

you can use the floatValue to get a CGFloat from an NSNumber

example:

CGFloat myFloat = [number floatValue];

What do I need to do to use tgmath on iOS?

I was able to get the tgmath.h functions to work by including the header at the top of my PCH file.

At some point (read: Xcode update) I had to start disabling Modules to get this to work. The details of such are in the question Dima links to below.

How to safely floor or ceil a CGFloat to int?

There are a couple misconceptions in your question.

what if my CGFloat is 2.0f but internally it is represented as 1.999999999999f

can't happen; 2.0, like all reasonably small integers, has an exact representation in floating-point. If your CGFloat is 2.0f, then it really is 2.0.

something like 2.0 would never accidentally get ceiled to 2

The ceiling of 2.0 is 2; what else would it possibly be?


I think the question that you're really asking is "suppose I do a calculation that produces an inexact result, which mathematically should be exactly 2.0, but is actually slightly less; when I apply floor to that value, I get 1.0 instead of 2.0--how do I prevent this?"

That's actually a fairly subtle question that doesn't have a single "right" answer. How have you computed the input value? What are you going to do with the result?



Related Topics



Leave a reply



Submit