NSNumber with representative number ( .0 ) not in NSString format - ios

Hi everyone,
I'm working with a private API and I need to send integer and double values.
For integers, I don't have any problem, I convert the integer to NSNumber and everything works fine.
But with double with no decimal numbers ( 46 for instance ) my request is rejected because the server sees an integer where there should be a double.
My sys admin told me to send round double value with ".0", so if I want to send the double 46, I have to send 46.0.
The problem is that I can't send an NSString or the server will also reject my request ( it will see a string where there should be a double ).
So here is my question : is there a way to add representative numbers to NSNumbers ? So my double 46 would be NSNumber 46.0
Can anyone help me ?
Thanks in advance.

When ever you are initialising the NSNumber you should use
mynumber = [NSNumber numberWithDouble: myDoublevalue];
and when you want to send it to server try like
[mynumber doubleValue];

I guess the question is: What do you use to create your NSNumber?
Using
NSNumber *intNumber = #(46);
Will give you an NSNumber that contains an int, whereas
NSNumber *doubleNumber = [NSNumber numberWithDouble:46];
should result in an NSNumber containing a double .
(You can check this by calling [intNumber objCType], which will give "i" and [doubleNumber objCType will give "d")
The other problem you might experience is that you (or the API you use) uses some format conversion to JSON or something else.
Normal JSON converters will omit the .0 and therefore you might get an error.
Therefore if you have access to the JSON (or what ever else format conversion you use, since you will never send an NSNumber to any server), you can fix it there.
Last point, if nothing helps with the two points above, you could think about adding a very small number, that will force a point, but won't make much of a difference in normal cases:
input = pow(2,log2(fabs(input))-50) //use 20 instead of 50 for float numbers!
NSNumber *result = #(input);

Related

int not returning same value from NSString

I have saved value in Singletone as NSString. When I want to convert to int, value is some random number. For example, I am calling NSString *numberCoupons = [Manager sharedInstance].userProfile.numberOfCoupons, po numberCoupons returning normal value: 40.
But problem is in next line, when I want to convert string to value: int coupons = (int)numberCoupons; It is returning some random number, etc. 421414.
What could be the problem?
try int coupons = [numberCoupons integerValue];
numerofCoupons is obviously an NSNumber object which is used to store numbers within Objective-C collection classes (NSArray, NSDictionary, etc) as only objects can be stored in them.
To get the wrapped value out of the object use:
NSInteger coupons = [numberOfCoupons integerValue]
I would recommend redeclaring numberOfCoupons as NSInteger, and not NSNumber, as NSNumber objects are difficult and expensive to manipulate compared to the primitive types they wrap.
If the value needs to go into a collection class then wrap it in an NSNumber object when adding it and unwrap it when removing it.
When you write (int)numberOfCoupons you are asking that the value in the variable numberOfCoupons be cast to the type int.
Now the value in a variable of type NSString * is a reference to an object, that is a memory address. When (Objective-)C casts a reference to an integer type you get back the memory address. This is the “random” value you are seeing.
What you need to do is send a message to the object referenced by the value in your variable requesting that it return an integer value equivalent to itself. NSString has a method intValue for this, so [numberOfCoupons intValue] will do what you wish.
There is a whole family of xValue methods to obtain various integer and floating-point values of different precision/size.
Note: if you have a reference to an NSNumber, rather than an NSString, then exactly the same code will work.
Note 2: if you do have an NSNumber then the cast expression you first tried may return a value which has a completely different magnitude than you might expect for a memory address. This is because some integer values are represented by special tagged addresses which don't actually reference a real object. This is an optimisation you normally would not notice, except when you accidentally cast the reference value to an integer...
HTH

Efficiency NSString vs NSInteger/int - only for textual representation

I'd like to know if it would make any sense to cast/convert a number, parsed from a csv file, e.g. customer id, to a NSString?
Or maybe better a simple int? As I'm quite new to obj-c, I'm not really sure, wether to consistently use the NSxyz types, or use what I'm used to, coming from Java/C/C++.
Actually the value only is stored in a variable, and then loaded into some textfields (which again would imply a conversion back to NSString I guess?).
Would there be any benefit in less memory being used? Let's assume the ids had 6 digits, parsing roughly 10'000-100'000 customers. Same would apply to smaller numbers, e.g. the addresses street number.
In a string, 1 letter == 1 byte, so if you have 6 digits, you are occupying 6 bytes.
An int instead takes generally 2 (short), 3 or 4 (long) bytes. It can arrive also to 8 bytes with an int_64. But, you are limited because for example in the 2 byte case (16 bit) you can consider 2^16 numbers.
In your case you could use an int, but i would use an NSString, also because you need it in your textfield.
An NSInteger is an int. An NSUInteger is an unsigned int.
An NSNumber is an Object (so no primitive) which can store an int, a float, a double or a boolean. So you can store many type of primitive in this type of variable and then use the appropriate:
[number floatValue];
[number boolValue];
...

How are integers stored in iOS, in particular in .pList and CoreData [duplicate]

This question already has an answer here:
Integers not properly returned from a property list (plist) array in Objective-C
(1 answer)
Closed 8 years ago.
I am trying to take a small integer (eg 4) from a pList and put it into a managed object for later manipulation. However, by the time I come to take it out of the managed object and put it into an NSInteger it has changed completely. 4 has become 237371328 !
The number is stored as "Number" in the pList and integer 16 in the managed object.
I have two fields: timesAsNumber which is integer 16 and timesUsed which is string (my current work around!).
The lines of code involved are:
NSArray *usageFetchResults = [self.objectContext executeFetchRequest:request error:&error];
NSLog(#"Here is the usageArray: %#, with error: %#",usageFetchResults, error);
This gives the log result:
data: {\n feature = video;\n timesAsNumber = 4;\n timesUsed = 4;\n})"
), with error: (null)
So the logger knows the value of timesAsNumber is 4.
NSLog(#"timesAsNumber straight from the Managed Object: %#", [currentUseData valueForKey:#"timesAsNumber"]);
Produces result: timesAsNumber straight from the Managed Object: 4 so still no problem.
However,
NSInteger timesUsedAsInt = [currentUseData valueForKey:#"timesAsNumber"];
NSLog(#"times As Number now reads: %ld", (long)timesUsedAsInt);
Produces the result: times As Number now reads: 237371328
I need to have the number as an integer for manipulation and my workaround of storing as string and converting to and fro is hardly elegant!
I teach High School computing so I know about storage of floating point numbers: excess-127, twos complement etc. I assume the problem arises from the different ways the integer is stored in the pList, the managed object and the NSInteger. However, I cannot figure out what those storage methods are so that I can work with them.
Any help gratefully received.
Tim.
When you are storing a number in plist or coreData, it is stored as NSNumber. So you access the value as NSInteger myInt = myNumber.intValue. When you are converting it back, use NSNumber *myNumber = [NSNumber numberWithInt:myInt]. That large number (237371328) could appear because you forgot to convert the NSNumber to int. Hope this helps.
Edit:
Try:
NSInteger timesUsedAsInt = [[currentUseData valueForKey:#"timesAsNumber"] intValue];
NSLog(#"times As Number now reads: %ld", (long)timesUsedAsInt);

NSJSONSerialization output number as float?

I'm using NSJSONSerialization to convert a dictionary into JSON.
If I include an NSDecimalNumber ( == 0 ) in that dictionary it outputs as 0. This is wrong. 0 is an int. I need it to output as 0.0.
This is what I'm doing:
NSDecimalNumber *decimal = [[NSDecimalNumber alloc] initWithFloat:0.0f];
// when fed into NSJSONSerialization it outputs as 0
Is there any way to output as 0.0?
OR am I incorrect in my assumption? Is 0 a valid float?
There is no way to affect the way NSJSONSerialization outputs numbers. But you really should not worry about this. JSON doesn’t distinguish between different types of numbers, so you always should accept numbers with and without decimal points, no matter what the actual type of number you are doing your calculations with.

iOS: Find out number of fraction digits [duplicate]

This question already has answers here:
digits after decimal point
(2 answers)
How to calculate number of digits after floating point in iOS?
(3 answers)
Closed 9 years ago.
I have some numbers that comes from server, how to know how many fraction digits in number ?
I mean how to know that 2.43 has 2 numbers after coma, 3.145 - 3 numbers, 2.0003 - 4 numbers.
Thanks in advance..
Assuming you are using a number, change it to a string. Remove the decimal point and get the last object and the length.
Example:
NSNumber *number = [NSNumber numberWithFloat:3.902];
[number.stringValue componentsSeparatedByString: #"."].lastObject.length;
I would do this :
NSNumber *number = [[NSNumber alloc] initWithFloat:3.902];
NSUInteger i = [[number stringValue] rangeOfString:#"."].location;
long numberOfDigits = [[number stringValue] length]-(i+1);
NSLog(#"%ld", numberOfDigits);
3
convert to string.
find the decimal point range.
subtract string length from the decimal point position and Add one.
Do you mean that you are retrieving the data from a server in a stream?
If your getting the data as a stream, it should be prepended with the length of the string, that is how you would know how many places to expect.
So on the server, first convert to string, then determine the length, or use another method suggested, then prepend the length of the string, and then send that number first.

Resources