I do not see how adding something like L to a number makes a difference. For example if I took the number 23.54 and made it 23.54L what difference does that actually make and when should I use the L and not use the L or other add ons like that? Doesn't objective-c already know 23.54 is a long so why would I make it 23.54L in any case?
If someone could explain that'd be great thanks!
Actually, when a number has a decimal point like 23.54 the default interpretation is that it's a double, and it's encoded as a 64-bit floating point number. If you put an f at the end 23.54f, then it's encoded as a 32-bit floating pointer number. Putting an L at the end declares that the number is a long double, which is encoded as a 128-bit floating point number.
In most cases, you don't need to add a suffix to a number because the compiler will determine the correct size based on context. For example, in the line
float x = 23.54;
the compiler will interpret 23.54 as a 64-bit double, but in the process of assigning that number to x, the compiler will automatically demote the number to a 32-bit float.
Here's some code to play around with
NSLog( #"%lu %lu %lu", sizeof(typeof(25.43f)), sizeof(typeof(25.43)), sizeof(typeof(25.43L)) );
int x = 100;
float y = x / 200;
NSLog( #"%f", y );
y = x / 200.0;
NSLog( #"%f", y );
The first NSLog displays the number of bytes for the various types of numeric constants. The second NSLog should print 0.000000 since the number 200 is interpreted as in integer, and integer division truncates to an integer. The last NSLog should print 0.500000 since 200.0 is interpreted as a double.
It's a way to force the compiler to treat a constant with a specific type.
23.45 is double, 23.54L is long double, and 23.54f is float.
Use a suffix when you need to specify the type of a constant. Or, create a variable of a specific type: float foo = 23.54;. Most of the time you don't need a suffix.
This is all plain C.
Related
hi i am new to obj C and i am assigning a text field value to int variable PaidLeaves as below:
because text field return string value i have to cat it to int value so i use following code:
for example
PaidLeaves = txtPaidLeaves.text.intValue;
and
PaidLeaves = txtPaidLeaves.text.integerValue;
above i am assigning a text field value to int value
and both works but what is difference between two expression
please tell me
thank you
intValue returns an int number.
integerValue returns a NSInteger number.
The difference between them is their number of bits, or in easier terms, the range of values that they can store. Has said in an answer of a different question:
int is always 32-bits.
long long is always 64-bits.
NSInteger and long are always pointer-sized. That means they're
32-bits on 32-bit systems, and 64 bits on 64-bit systems.
Reference: https://stackoverflow.com/a/4445467/4370893
Consider that Apple has only made 64 bit systems since Mac OS X 10.7 (Lion), which was released in 2011, so I'm gonna refer to NSInteger has a 64 bit long integer.
So what that means?
The first bit of a signed integer number, like NSInteger and int, is used to define if it's a positive or a negative number. The conclusion is that a signed integer number goes from -2^(number of bits-1) to 2^(number of bits-1)-1, so...
int: - 2,147,483,648 (- 2^31) to 2,147,483,647 (2^31-1)
NSInteger: - 9,223,372,036,854,775,808 (- 2^63) to 9,223,372,036,854,775,807 (2^63-1)
I am looking a few hours for some solution of this problem, but I don't get how it works. I have a hex string from delphi double value : 0X3FF0000000000000. That value should be 1.0. It is 8 byte long, first bit is sign, next 11 are exponent and the rest is mantissa. So for me is this hex value equals 0 x 10^(1023). Maybe I am wrong somewhere, but it doesn't matter. The point is, I need this hex value to convert into objective c double value. If I do: (double)strtoll(hexString.UTF8String, NULL,16); I get: 4.607...x 10 ^18. What am I doing wrong?
It seems that trying to cast in this way ends up with a call to an implicit type conversion (calls _ultod3 or _ltod3) that alters the underlying data. In fact, even trying to do this seems to do the same thing :
UINT64 temp1 = strtoull(hexString, NULL, 16);
double val = *&temp1;
But if you cast the uint pointer to a double* it semes to suppress the compiler's desire to try to perform a conversion. Something like this should work :
UINT64 temp1 = strtoull(hexString, NULL, 16);
double val = *(double*)&temp1;
At least this works with the MS C++ compiler... I imagine the objective C compiler would cooperate as well.
Right now I have a line of code like this:
float x = (([self.machine micSensitivity] - 0.0075f) / 0.00025f);
Where [self.machine micSensitivity] is a float containing the value 0.010000
So,
0.01 - 0.0075 = 0.0025
0.0025 / 0.00025 = 10.0
But in this case, it keeps returning 9.999999
I'm assuming there's some kind of rounding error but I can't seem to find a clean way of fixing it. micSensitivity is incremented/decremented by 0.00025 and that formula is meant to return a clean integer value for the user to reference so I'd rather get the programming right than just adding 0.000000000001.
Thanks.
that formula is meant to return a clean integer value for the user to reference
If that is really important to you, then why do you not multiply all the numbers in this story by 10000, coerce to int, and do integer arithmetic?
Or, if you know that the answer is arbitrarily close to an integer, round to that integer and present it.
Floating-point arithmetic is binary, not decimal. It will almost always give rounding errors. You need to take that into account. "float" has about six digit precision. "double" has about 15 digits precision. You throw away nine digits precision for no reason.
Now think: What do you want to display? What do you want to display if the result of your calculation is 9.999999999? What would you want to display if the result is 9.538105712?
None of the numbers in your question, except 10.0, can be exactly represented in a float or a double on iOS. If you want to do float math with those numbers, you will have rounding errors.
You can round your result to the nearest integer easily enough:
float x = rintf((self.machine.micSensitivity - 0.0075f) / 0.00025f);
Or you can just multiply all your numbers, including the allowed values of micSensitivity, by 4000 (which is 1/0.00025), and thus work entirely with integers.
Or you can change the allowed values of micSensitivity so that its increment is a fraction whose denominator is a power of 2. For example, if you use an increment of 0.000244140625 (which is 2-12), and change 0.0075 to 0.00732421875 (which is 30 * 2-12), you should get exact results, as long as your micSensitivity is within the range ±4096 (since 4096 is 212 and a float has 24 bits of significand).
The code you have posted is correct and functioning properly. This is a known side effect of using floating point arithmetic. See the wiki on floating point accuracy problems for a dull explanation as to why.
There are several ways to work around the problem depending on what you need to use the number for.
If you need to compare two floats, then most everything works OK: less than and greater than do what you would expect. The only trouble is testing if two floats are equal.
// If x and y are within a very small number from each other then they are equal.
if (fabs(x - y) < verySmallNumber) { // verySmallNumber is usually called epsilon.
// x and y are equal (or at least close enough)
}
If you want to print a float, then you can specify a precision to round to.
// Get a string of the x rounded to five digits of precision.
NSString *xAsAString = [NSString stringWithFormat:#"%.5f", x];
9.999999 is equal 10. there is prove:
9.999999 = x then 10x = 99.999999 then 10x-x = 9x = 90 then x = 10
What is the difference between objective-c C primitive numbers? I know what they are and how to use them (somewhat), but I'm not sure what the capabilities and uses of each one is. Could anyone clear up which ones are best for some scenarios and not others?
int
float
double
long
short
What can I store with each one? I know that some can store more precise numbers and some can only store whole numbers. Say for example I wanted to store a latitude (possibly retrieved from a CLLocation object), which one should I use to avoid loosing any data?
I also noticed that there are unsigned variants of each one. What does that mean and how is it different from a primitive number that is not unsigned?
Apple has some interesting documentation on this, however it doesn't fully satisfy my question.
Well, first off types like int, float, double, long, and short are C primitives, not Objective-C. As you may be aware, Objective-C is sort of a superset of C. The Objective-C NSNumber is a wrapper class for all of these types.
So I'll answer your question with respect to these C primitives, and how Objective-C interprets them. Basically, each numeric type can be placed in one of two categories: Integer Types and Floating-Point Types.
Integer Types
short
int
long
long long
These can only store, well, integers (whole numbers), and are characterized by two traits: size and signedness.
Size means how much physical memory in the computer a type requires for storage, that is, how many bytes. Technically, the exact memory allocated for each type is implementation-dependendant, but there are a few guarantees: (1) char will always be 1 byte (2) sizeof(short) <= sizeof(int) <= sizeof(long) <= sizeof(long long).
Signedness means, simply whether or not the type can represent negative values. So a signed integer, or int, can represent a certain range of negative or positive numbers (traditionally –2,147,483,648 to 2,147,483,647), and an unsigned integer, or unsigned int can represent the same range of numbers, but all positive (0 to 4,294,967,295).
Floating-Point Types
float
double
long double
These are used to store decimal values (aka fractions) and are also categorized by size. Again the only real guarantee you have is that sizeof(float) <= sizeof(double) <= sizeof (long double). Floating-point types are stored using a rather peculiar memory model that can be difficult to understand, and that I won't go into, but there is an excellent guide here.
There's a fantastic blog post about C primitives in an Objective-C context over at RyPress. Lots of intro CPS textbooks also have good resources.
Firstly I would like to specify the difference between au unsigned int and an int. Say that you have a very high number, and that you write a loop iterating with an unsigned int:
for(unsigned int i=0; i< N; i++)
{ ... }
If N is a number defined with #define, it may be higher that the maximum value storable with an int instead of an unsigned int. If you overflow i will start again from zero and you'll go in an infinite loop, that's why I prefer to use an int for loops.
The same happens if for mistake you iterate with an int, comparing it to a long. If N is a long you should iterate with a long, but if N is an int you can still safely iterate with a long.
Another pitfail that may occur is when using the shift operator with an integer constant, then assigning it to an int or long. Maybe you also log sizeof(long) and you notice that it returns 8 and you don't care about portability, so you think that you wouldn't lose precision here:
long i= 1 << 34;
Bit instead 1 isn't a long, so it will overflow and when you cast it to a long you have already lost precision. Instead you should type:
long i= 1l << 34;
Newer compilers will warn you about this.
Taken from this question: Converting Long 64-bit Decimal to Binary.
About float and double there is a thing to considerate: they use a mantissa and an exponent to represent the number. It's something like:
value= 2^exponent * mantissa
So the more the exponent is high, the more the floating point number doesn't have an exact representation. It may also happen that a number is too high, so that it will have a so inaccurate representation, that surprisingly if you print it you get a different number:
float f= 9876543219124567;
NSLog("%.0f",f); // On my machine it prints 9876543585124352
If I use a double it prints 9876543219124568, and if I use a long double with the .0Lf format it prints the correct value. Always be careful when using floating points numbers, unexpected things may happen.
For example it may also happen that two floating point numbers have almost the same value, that you expect they have the same value but there is a subtle difference, so that the equality comparison fails. But this has been treated hundreds of times on Stack Overflow, so I will just post this link: What is the most effective way for float and double comparison?.
I'm passing a float to a method but it's not showing all decimals. I have no idea why this is happening.
Here's an example:
[[LocationApiCliente sharedInstance] nearPlacesUsingLatitude:-58.3645248331830402 andLongitude:-34.6030467894227982];
Then:
- (BOOL)nearPlacesUsingLatitude:(double)latitude andLongitude:(double) longitude {
NSString *urlWithCoords = [NSString stringWithFormat:#"%#&lat=%f&long=%f", CountriesPath, latitude, longitude];
Printing urlWithCoords will result in:
format=json&lat=-58.364525&long=-34.603047
More of this. What I'm getting from the output terminal:
(lldb) p -3.13419834918349f
(float) $4 = -3.1342
(lldb) p -3.13419834918349
(double) $5 = -3.1342
Any ideas?
Change the %fs in your formatting strings to specify the desired number of decimals, e.g., %.16f.
Note that the number of decimals shown does not guarantee that they are correct, but at least they won't be truncated.
Overall the problem is that floating point numbers do not contain information about the precision, and cannot precisely represent some decimal values, so formatting can not in the general case “autodetect” the number of decimals. So you just need to override the default by specifying the desired number and accept that it's not representative of location accuracy. But since you seem to be passing the floats to another program via the URL, this shouldn't be a problem—a larger number of decimals is better.
It looks like CoreLocation uses doubles to represent degrees, so I'd be surprised if there's any more geographic precision to be found on the device.
But, in general, if you want to represent higher precision than double, you can use long double in Objective-C like this...
long double myPi = 3.141592653589793;
NSLog(#"%16.16Lf", myPi);