This is the code I'm using to pull a number from a dictionary,
int num = [[sharedManager.data objectForKey:#"sum(units.num)"]intValue];
This is the key/value of the number which is printed in the debugger.
key = (__NSCFString *) #"sum(units.num)" 0x176d4d40
value = (__NSCFNumber *) (long)38244 0x176ca850
And this is the result I'm getting,
num = (int) 393051808
What i need is for num to be 38244.
Does anyone know why I'm getting this result?
Thanks
Paul.
What you are getting is , the integer representation (393051808) of your key's memory address (0x176d4d40).
Do this,
NSNumber *number = [sharedManager.data objectForKey:#"sum(units.num)"];
int num = [number intValue];
// or
long num = [number longValue]; //because your number is a long value
Related
I am trying to sort some list of strings. And names of elements could be almost anything, from real names, strings, dates,... and numbers.
I found NSStringCompareOptions with NSNumericSearch, wich work fast enough and it work nice so :
[1,2,21,3,55,6] --> [1,2,3,6,21,55]
But my problems are negative numbers
[1,2,3,-1,-4,-5] --> [-1,-4,-5,1,2,3]
What it is not right.
I know that Apple stays :
Numeric comparison only applies to the numerals in the string,
not other characters that would have meaning in a numeric representation
such as a negative sign, a comma, or a decimal point.
But my question is how to achieve this, because I know I am not only who do this.
EDIT :
Thanks to Narendra Pandey, but my real case is a little bit complicated, so his answer can't be used here.
So let say I have some dictionary with numbers as keys and strings as values :
dic = {#1:#"123", #2:#"-123", #5:"MyName",...};
then I have array of object with ids.
array = #[{object with id 5}, {object with id 2},...];
and I need sorted array of object by name of properties.
NSStringCompareOptions comparisonOption = NSCaseInsensitiveSearch | NSNumericSearch;
array = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString * name1 = [dic objectForKey:obj1.someId];
NSString * name2 = [dic objectForKey:obj2.someId];
return [name1 compare:name2 options:comparisonOption];;
}];
EDIT 2:
Maybe I should state that I have solution, but it is 4 times slower that sorting with NSStringCompareOptions
// CHECK IF IT IS NUMBER
NSNumber * number1 = [numberFormatter numberFromString:string1];
NSNumber * number2 = [numberFormatter numberFromString:string2];
//
// NSLog(#"NUMBERS : %#, %#", number1, number2);
if (number1 && number2) {
return [number1 compare:number2];
}
return [string1 compare:string2 options:comparisonOption];
NSArray * numbers = #[#1, #2, #3, #-4, #-5, #6, #9];
NSPredicate * predicateForPositive = [NSPredicate predicateWithFormat:#"integerValue >= 0"];
NSArray * positiveNumbers = [numbers filteredArrayUsingPredicate:predicateForPositive];
NSPredicate * predicateForNegative = [NSPredicate predicateWithFormat:#"integerValue <= 0"];
NSArray * NegativeNumber = [numbers filteredArrayUsingPredicate:predicateForNegative];
NSLog(#"Negative number %#",NegativeNumber);
NSLog(#"Positive number %#",positiveNumbers);
Output:
Negative number (
"-4",
"-5"
)
Positive number (
1,
2,
3,
6,
9
)
Now sort both and concate both Array.
Thanks to Narendra Pandey I found solution for me.
Let me state first that Narendra Pandey solution works, but it is slower, even 3 times.
(in my case 0.014s with NSStringCompareOptions, and 0,042 Narendra Pandey solution).
But if I use his idea and change it a little bit :
array = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString * name1 = somehow get string1;
NSString * name2 = somehow get string2;
if ([string1 integerValue] <0 && [string2 integerValue]<0) {
return - [string1 compare:string2 options:comparisonOption];
}
return [string1 compare:string2 options:comparisonOption];
}];
this method is faster, in my case 0,015s which is comparable with NSStringCompareOptions.
In this way you avoid to go through whole array at beginning to separate negative and positive numbers, and then sort them.
This function get any array and convert it to sorted Double array
var numberArray: [Any] = [4, 3.9, -23,3, 7.6, -51, 75.3, "0", "-(22)"]
/// This function get any array and convert it to sorted _Double_ array
/// - Note: Non-numerical elements are automatically removed from the array
/// - Parameters:
/// - numbers: array of anything
/// - Returns: sorted _Double_ array
func sortAnyNumbers(_ numbers: [Any]) -> [Double] {
var _numbers: [Double] = []
numbers.forEach { number in
// Delete non-numeric characters
if let numb = Double("\(number)".components(separatedBy: CharacterSet(charactersIn: "-01234567890.").inverted).joined()) {
_numbers.append(numb)
}
}
return _numbers.sorted()
}
print(sortAnyNumbers(numberArray)) //[-51.0, -23.0, -22.0, 0.0, 3.0, 3.9, 4.0, 7.6, 75.3]
I am making a game that requires me to use very large numbers. I believe I am able to store very large numbers with NSDecimal. However, when displaying the numbers to users I would like to be able to convert the large number to a succinct string that uses characters to signify the value eg. 100,000 -> 100k 1,000,000 -> 1.00M 4,200,000,000 -> 4.20B and so forth going up to extremely large numbers. Is there any built in method for doing so or would I have to use a bunch of
NSDecimalCompare statements to determine the size of the number and convert?
I am hoping to use objective c for the application.
I know that I can use NSString *string = NSDecimalString(&NSDecimal, _usLocale); to convert to a string could I then do some type of comparison on this string to get the result I'm looking for?
Use this method to convert your number into a smaller format just as you need:
-(NSString*) suffixNumber:(NSNumber*)number
{
if (!number)
return #"";
long long num = [number longLongValue];
int s = ( (num < 0) ? -1 : (num > 0) ? 1 : 0 );
NSString* sign = (s == -1 ? #"-" : #"" );
num = llabs(num);
if (num < 1000)
return [NSString stringWithFormat:#"%#%lld",sign,num];
int exp = (int) (log(num) / 3.f); //log(1000));
NSArray* units = #[#"K",#"M",#"G",#"T",#"P",#"E"];
return [NSString stringWithFormat:#"%#%.1f%#",sign, (num / pow(1000, exp)), [units objectAtIndex:(exp-1)]];
}
Some sample examples:
NSLog(#"%#",[self suffixNumber:#99999]); // 100.0K
NSLog(#"%#",[self suffixNumber:#5109999]); // 5.1M
Source
Solved my issue: Can only be used if you know that your NSDecimal that you are trying to format will only be a whole number without decimals so make sure you round when doing any math on the NSDecimals.
-(NSString *)returnFormattedString:(NSDecimal)nsDecimalToFormat{
NSMutableArray *formatArray = [NSMutableArray arrayWithObjects:#"%.2f",#"%.1f",#"%.0f",nil];
NSMutableArray *suffixes = [NSMutableArray arrayWithObjects:#"k",#"M",#"B",#"T",#"Qa",#"Qi",#"Sx",#"Sp",#"Oc",#"No",#"De",#"Ud",#"Dud",#"Tde",#"Qde",#"Qid",#"Sxd",#"Spd",#"Ocd",#"Nvd",#"Vi",#"Uvi",#"Dvi",#"Tvi", nil];
int dick = [suffixes count];
NSLog(#"count %i",dick);
NSString *string = NSDecimalString(&nsDecimalToFormat, _usLocale);
NSString *formatedString;
NSUInteger characterCount = [string length];
if (characterCount > 3) {
NSString *trimmedString=[string substringToIndex:3];
float a;
a = 100.00/(pow(10, (characterCount - 4)%3));
int remainder = (characterCount-4)%3;
int suffixIndex = (characterCount + 3 - 1)/3 - 2;
NSLog(#"%i",suffixIndex);
if(suffixIndex < [suffixes count]){
NSString *formatSpecifier = [formatArray[remainder] stringByAppendingString:suffixes[suffixIndex]];
formatedString= [NSString stringWithFormat:formatSpecifier, [trimmedString floatValue] / a];
}
else {
formatedString = #"too Big";
}
}
else{
formatedString = string;
}
return formatedString;
}
I have to count how many decimal digits are there in a double in Xcode 5. I know that I must convert my double in a NSString, but can you explain me how could I exactly do? Thanks
A significant problem is that a double has a fractional part which has no defined length. If you know you want, say, 3 fractional digits, you could do:
[[NSString stringWithFormat:#"%1.3f", theDoubleNumber] length]
There are more elegant ways, using modulo arithmetic or logarithms, but how elegant do you want to be?
A good method could be to take your double value and, for each iteration, increment a counter, multiply your value by ten, and constantly check if the left decimal part is really near from zero.
This could be a solution (referring to a previous code made by Graham Perks):
int countDigits(double num) {
int rv = 0;
const double insignificantDigit = 8;
double intpart, fracpart;
fracpart = modf(num, &intpart);
while ((fabs(fracpart) > 0.000000001f) && (rv < insignificantDigit))
{
num *= 10;
fracpart = modf(num, &intpart);
rv++;
}
return rv;
}
You could wrap the double in an instance of NSNumber and get an NSString representation from the NSNumber instance. From there, calculating the number of digits after the decimal could be done.
One possible way would be to implement a method that takes a double as an argument and returns an integer that represents the number of decimal places -
- (NSUInteger)decimalPlacesForDouble:(double)number {
// wrap double value in an instance of NSNumber
NSNumber *num = [NSNumber numberWithDouble:number];
// next make it a string
NSString *resultString = [num stringValue];
NSLog(#"result string is %#",resultString);
// scan to find how many chars we're not interested in
NSScanner *theScanner = [NSScanner scannerWithString:resultString];
NSString *decimalPoint = #".";
NSString *unwanted = nil;
[theScanner scanUpToString:decimalPoint intoString:&unwanted];
NSLog(#"unwanted is %#", unwanted);
// the number of decimals will be string length - unwanted length - 1
NSUInteger numDecimalPlaces = (([resultString length] - [unwanted length]) > 0) ? [resultString length] - [unwanted length] - 1 : 0;
return numDecimalPlaces;
}
Test the method with some code like this -
// test by changing double value here...
double testDouble = 1876.9999999999;
NSLog(#"number of decimals is %lu", (unsigned long)[self decimalPlacesForDouble:testDouble]);
results -
result string is 1876.9999999999
unwanted is 1876
number of decimals is 10
Depending on the value of the double, NSNumber may do some 'rounding trickery' so this method may or may not suit your requirements. It should be tested first with an approximate range of values that your implementation expects to determine if this approach is appropriate.
I am fetching data from the web, and I am having problems with the numbers that are returned. For example, when the int 1 is returned from the server, and I try and convert that int to a NSNumber, the value of the NSNumber is 151241152. The number is slightly different every time, but it is always over 1 billion. Here is my code:
int agrees = (int)[info objectForKey:kWaveAgrees];
wave.numberOfAgrees = [NSNumber numberWithInt:agrees];
Does anyone know why this is happening?
NSNumber is an object. You cannot cast it into an int, it must be unboxed first.
int agrees = [[info objectForKey:kWaveAgrees] intValue];
I'm trying to use a dictionary which I got as a JSON response from my server. When I print the description of the dictionary, everything is in order
Printing description of dict:
{
category = 1;
code = 1;
name = "xxxx";
pictureUrl = "xxxx";
sessionId = xxx;
status = 0;
}
I need the "code" value, and when I use objectForKey:#"code" to get it, I get a wrong value:
int code = [NSDictionary objectForKey:#"code"];
After this i print out the value of code and its something like 3483765348, which is very, very wrong.
Why is this happening?
The object returned is an NSNumber and not an int (which isn't an object).
If you want the int value try this
int code = [[myDictionary objectForKey:#"code"] intValue];
Try the following code which will be use to solve your issue.. As per your code it returns only value you have to convert it to int value.Use this piece of code
int code = [[NSDictionary objectForKey:#"code"]intValue];
Hope this Helps !!!
-objectForKey: doesn't return an int, but an object instead (in your case of type NSNumber).
NSNumber *code = [myDict objectForKey:#"code"];
NSInteger codeInteger = [code integerValue];
int code = [[yourResultingDictionary objectForKey:#"code"] intValue];
I think it will be helpful to you.
The object key returns only for array values, so you will use value for key path.
user_idstr = [tweet valueForKeyPath:#"properties.user_id"];