I'm comparing two NSUInteger, I kept getting crash thats says -[__NSCFNumber length]: unrecognized selector sent to instance
NSUInteger index = [masterArray indexOfObject:object];
if (index != NSNotFound){
if (index < [anArray count] - 1 ){
//Do something
}
else{
//Do something
}
}
Reading old post of similar question, but I still can't figure this out. I've tried to cast and it still crash:
NSUInteger index = [masterArray indexOfObject:object];
if (index != NSNotFound){
if (index < (NSUInteger)((int)[anArray count] - 1) ){
//Do something
}
else{
//Do something
}
}
However, without any minus operation, it works.
NSUInteger index = [masterArray indexOfObject:object];
if (index != NSNotFound){
if (index < [anArray count]){
//Do something
}
else{
//Do something
}
}
Any idea why? Thanks in advance.
the array is not the problem.
See what happens in the following example.
NSUInteger i = 0;
NSLog(#"%#", i-1==NSUIntegerMax ? #"YES" : #"NO" );
//output: YES
NSLog(#"NSUIntegerMax=%lu", NSUIntegerMax );
//output: NSUIntegerMax=18446744073709551615
NSLog(#"%lu", i-1 );
//output: 18446744073709551615
so when array count is 0 and you subtract 1 you end up with the NSUIntegerMax.
You compare array.count - 1 against a range of numbers that can't express signed (negative) numbers.
array.count is a property of type NSUInteger.
so in the following scenario will come up
when array.count == 0,
array.count - 1 == 18446744073709551615 // not!! -1
your if statements will not work as expected unless you really wanted to compare to NSUIntegerMax.
As you discovered casting to integer may help you out..
you will want to
if (index < ((int)array.count) - 1) {
} else {
}
because casting (NSUInteger)((int)array.count - 1) is still 18446744073709551615 == NSUIntegerMax when array.count < 1
you could also go without casting for this solution
if (index + 1 >= array.count) {
} else {
}
Related
I'm running into a frustrating problem with a parentheses completion algorithm. The math library I'm using, DDMathParser, only processes trigonometric functions in radians. If one wishes to use degrees, they must call dtor(deg_value). The problem is that this adds an additional parenthesis that must be accounted for at the end.
For example, the math expression sin(cos(sin(x))) would translate to sin(dtor(cos(dtor(sin(dtor(x))) in my code. However, notice that I need two additional parentheses in order for it to be a complete math expression. Hence, the creation of resolve_dtor().
Here is my attempted solution, the idea was to have 0 signify a left-paren, 1 signify a left-paren with dtor(, and 2 signify a right-paren thus completing either 0 or 1.
- (NSMutableString *)resolve_dtor:(NSMutableString *)exp
{
NSInteger mutable_length = [exp length];
NSMutableArray *paren_complete = [[NSMutableArray alloc] init]; // NO/YES
for (NSInteger index = 0; index < mutable_length; index++) {
if ([exp characterAtIndex:index] == '(') {
// Check if it is "dtor()"
if (index > 5 && [[exp substringWithRange:NSMakeRange(index - 4, 4)] isEqual:#"dtor"]) {
//dtor_array_index = [self find_incomplete_paren:paren_complete];
[paren_complete addObject:#1];
}
else
[paren_complete addObject:#0]; // 0 signifies an incomplete parenthetical expression
}
else if ([exp characterAtIndex:index] == ')' && [paren_complete count] >= 1) {
// Check if "dtor("
if (![self elem_is_zero:paren_complete]) {
// Add right-paren for "dtor("
[paren_complete replaceObjectAtIndex:[self find_incomplete_dtor:paren_complete] withObject:#2];
[exp insertString:#")" atIndex:index + 1];
mutable_length++;
index++;
}
else
[paren_complete replaceObjectAtIndex:[self find_incomplete_paren:paren_complete] withObject:#2];
}
else if ([paren_complete count] >= 1 && [[paren_complete objectAtIndex:0] isEqualToValue:#2]) {
// We know that everything is complete
[paren_complete removeAllObjects];
}
}
return exp;
}
- (bool)check_dtor:(NSMutableString *)exp
{
NSMutableArray *paren_complete = [[NSMutableArray alloc] init]; // NO/YES
for (NSInteger index = 0; index < [exp length]; index++) {
if ([exp characterAtIndex:index] == '(') {
// Check if it is "dtor()"
if (index > 5 && [[exp substringWithRange:NSMakeRange(index - 4, 4)] isEqual:#"dtor"]) {
//dtor_array_index = [self find_incomplete_paren:paren_complete];
[paren_complete addObject:#1];
}
else
[paren_complete addObject:#0]; // 0 signifies an incomplete parenthetical expression
}
else if ([exp characterAtIndex:index] == ')' && [paren_complete count] >= 1) {
// Check if "dtor("
if (![self elem_is_zero:paren_complete]) {
// Indicate "dtor(" at index is now complete
[paren_complete replaceObjectAtIndex:[self find_incomplete_dtor:paren_complete] withObject:#2];
}
else
[paren_complete replaceObjectAtIndex:[self find_incomplete_paren:paren_complete] withObject:#2];
}
else if ([paren_complete count] >= 1 && [[paren_complete objectAtIndex:0] isEqualToValue:#2]) {
// We know that everything is complete
[paren_complete removeAllObjects];
}
}
// Now step back and see if all the "dtor(" expressions are complete
for (NSInteger index = 0; index < [paren_complete count]; index++) {
if ([[paren_complete objectAtIndex:index] isEqualToValue:#0] || [[paren_complete objectAtIndex:index] isEqualToValue:#1]) {
return NO;
}
}
return YES;
}
It seems the algorithm works for sin((3 + 3) + (6 - 3)) (translating to sin(dtor((3 + 3) x (6 - 3))) but not sin((3 + 3) + cos(3)) (translating to sin(dtor((3 + 3) + cos(dtor(3)).
Bottom Line
This semi-solution is most likely overcomplicated (one of my common problems, it seems), so I was wondering if there might be an easier way to do this?
Solution
Here is my solution to #j_random_hacker's pseudo code he provided:
- (NSMutableString *)resolve_dtor:(NSString *)exp
{
uint depth = 0;
NSMutableArray *stack = [[NSMutableArray alloc] init];
NSRegularExpression *regex_trig = [NSRegularExpression regularExpressionWithPattern:#"(sin|cos|tan|csc|sec|cot)" options:0 error:0];
NSRegularExpression *regex_trig2nd = [NSRegularExpression regularExpressionWithPattern:#"(asin|acos|atan|acsc|asec|acot)" options:0 error:0];
// need another regex for checking asin, etc. (because of differing index size)
NSMutableString *exp_copy = [NSMutableString stringWithString:exp];
for (NSInteger i = 0; i < [exp_copy length]; i++) {
// Check for it!
if ([exp_copy characterAtIndex:i] == '(') {
if (i >= 4) {
// check if i - 4
if ([regex_trig2nd numberOfMatchesInString:exp_copy options:0 range:NSMakeRange(i - 4, 4)] == 1) {
[stack addObject:#(depth)];
[exp_copy insertString:#"dtor(" atIndex:i + 1];
depth++;
}
}
else if (i >= 3) {
// check if i - 3
if ([regex_trig numberOfMatchesInString:exp_copy options:0 range:NSMakeRange(i - 3, 3)] == 1) {
[stack addObject:#(depth)];
[exp_copy insertString:#"dtor(" atIndex:i + 1];
depth++;
}
}
}
else if ([exp_copy characterAtIndex:i] == ')') {
depth--;
if ([stack count] > 0 && [[stack objectAtIndex:[stack count] - 1] isEqual: #(depth)]) {
[stack removeObjectAtIndex:[stack count] - 1];
[exp_copy insertString:#")" atIndex:i + 1];
}
}
}
return exp_copy;
}
It works! Let me know if there are any minor corrections that would be good to add or if there is a more efficient approach.
Haven't tried reading your code, but I would use a simple approach in which we scan forward through the input string writing out a second string as we go while maintaining a variable called depth that records the current nesting level of parentheses, as well as a stack that remembers the nesting levels that need an extra ) because we added a dtor( when we entered them:
Set depth to 0.
For each character c in the input string:
Write it to the output.
Is c a (? If so:
Was the preceding token sin, cos etc.? If so, push the current value of depth on a stack, and write out dtor(.
Increment depth.
Is c a )? If so:
Decrement depth.
Is the top of the stack equal to depth? If so, pop it and write out ).
DDMathParser natively supports using degrees for trigonometric functions and will insert the relevant dtor functions for you. It'll even automatically insert it by doing:
#"sin(42°)"
You can do this by setting the angleMeasurementMode on the relevant DDMathEvaluator object.
i'm trying to get the values of an array randomly but i'm getting an error
here is my code so far:
NSMutableArray *validMoves = [[NSMutableArray alloc] init];
for (int i = 0; i < 100; i++){
[validMoves removeAllObjects];
for (TileClass *t in tiles ) {
if ([self blankTile:t] != 0) {
[validMoves addObject:t];
}
}
NSInteger pick = arc4random() % validMoves.count;
[self movePiece:(TileClass *)[validMoves objectAtIndex:pick] withAnimation:NO];
}
The error you're getting (an arithmetic exception) is because validMoves is empty and this leads to a division by zero when you perform the modulus operation.
You have to explicitly check for the case of an empty validMoves array.
Also you should use arc4random_uniform for avoiding modulo bias.
if (validMoves.count > 0) {
NSInteger pick = arc4random_uniform(validMoves.count);
[self movePiece:(TileClass *)[validMoves objectAtIndex:pick] withAnimation:NO];
} else {
// no valid moves, do something reasonable here...
}
As a final remark not that arc4random_uniform(0) returns 0, therefore such case should be avoided or you'll be trying to access the first element of an empty array, which of course will crash your application.
i'm trying to get the values of an array randomly but i'm getting an error
here is my code so far:
NSMutableArray *validMoves = [[NSMutableArray alloc] init];
for (int i = 0; i < 100; i++){
[validMoves removeAllObjects];
for (TileClass *t in tiles ) {
if ([self blankTile:t] != 0) {
[validMoves addObject:t];
}
}
NSInteger pick = arc4random() % validMoves.count;
[self movePiece:(TileClass *)[validMoves objectAtIndex:pick] withAnimation:NO];
}
The error you're getting (an arithmetic exception) is because validMoves is empty and this leads to a division by zero when you perform the modulus operation.
You have to explicitly check for the case of an empty validMoves array.
Also you should use arc4random_uniform for avoiding modulo bias.
if (validMoves.count > 0) {
NSInteger pick = arc4random_uniform(validMoves.count);
[self movePiece:(TileClass *)[validMoves objectAtIndex:pick] withAnimation:NO];
} else {
// no valid moves, do something reasonable here...
}
As a final remark not that arc4random_uniform(0) returns 0, therefore such case should be avoided or you'll be trying to access the first element of an empty array, which of course will crash your application.
I need to implement a method, which compares two strings for equality, considering some turkish letters as latin(e.g. ı = i). That's bottleneck in program, so it needs to be implemented as efficient as possible.
I can't use NSString compare: withOption:nsdiactricinsensitivesearch, because it doesn't work with turkish letters correctly.
Here's the implementation of my algorithm:
- (NSComparisonResult) compareTurkishSymbol:(unichar)ch with:(unichar)another
{
//needs to be implemented
//code like: if (ch == 'ı') doesn't work correctly
}
- (NSComparisonResult)compareTurkish:(NSString*)word with:(NSString*)another
{
NSUInteger i;
for (i =0; i < word.length; ++i) {
NSComparisonResult result =[self compareTurkishSymbol:[word characterAtIndex:i] with:[another characterAtIndex:i]];
if (result != NSOrderedSame) {
return result;
}
}
return another.length > word.length ? NSOrderedDescending : NSOrderedSame;
}
The problem is I can't compare unichars correctly. It doesn't compare correctly non-ascii symbols. How to deal with that?
Finally I found an answer.
unichar is unsigned short, that means every symbol has its code. So we can compare them not as chars but as numbers.
- (NSComparisonResult) compareTurkishSymbol:(unichar)ch with:(unichar)another
{
if (ch == 305) {//code of 'ı'
ch = 'i';
}
return ch - another;
}
This question already has answers here:
Closed 11 years ago.
Possible Duplicates:
How to convert floats to human-readable fractions?
Convert decimal to fraction in Objective-C?
I want to take a decimal, 5.50, which is in a variable, and divide only the fractional part by 0.0625, which is my accuracy point. This would give me 8, as in 8/16 or 1/2.
Then I would like to display that answer as 5 8/16 or 1/2 in a text field. I know some answers will return a decimal still and not a whole number when dividing by .0625, but I would round that answer, which would still give me to the nearest 16th. What would be the best way to do this? I would like to make a function so I can reuse it. Yes, I posted a similar question that was answered, but wasn't able to get it to work. I'm thinking there's a better and easier way to do this, so I've posted this. Thanks in advance.
Function:
- (NSString *)theFunction:(float)input {
NSArray * array = [NSarray initWithObjects:nil,nil#"1/8",nil,#"1/4",]
int fractions = lroundf((input - (int)input)/((float)1/(float)16));
if(fractions == 0 || fractions == 16) {
return [NSString stringWithFormat:#"%d",lroundf(input)];
} else {
return [NSString stringWithFormat:#"%d %d/16",(int)input,fractions];
}
}
Note:
The if statement converts 5 0/16 into 5 and 5 16/16 into 6.
If you prefer the 5 0/16 and 5 16/16 notation, replace the if statement by:
return [NSString stringWithFormat:#"%d %d/16",(int)input,fractions];
EDIT: (by Jason)
//Just to make it a little sweeter!
- (NSString *)theFunction:(float)input {
int fractions = lroundf((input - (int)input)/((float)1/(float)16));
if(fractions == 0 || fractions == 16) {
return [NSString stringWithFormat:#"%d",lroundf(input)];
} else if(fractions == 2) {
return [NSString stringWithFormat:#"%d 1/8",(int)input];
} else if(fractions == 4) {
return [NSString stringWithFormat:#"%d 1/4",(int)input];
} else if(fractions == 6) {
return [NSString stringWithFormat:#"%d 3/8",(int)input];
} else if(fractions == 8) {
return [NSString stringWithFormat:#"%d 1/2",(int)input];
} else if(fractions == 10) {
return [NSString stringWithFormat:#"%d 5/8",(int)input];
} else if(fractions == 12) {
return [NSString stringWithFormat:#"%d 3/4",(int)input];
} else if(fractions == 14) {
return [NSString stringWithFormat:#"%d 7/8",(int)input];
} else {
return [NSString stringWithFormat:#"%d %d/16",(int)input,fractions];
}
}
EDIT (Response to edit by Jason)
I optimized your code, this way it's much cleaner.
Also check the code below, I think it's more efficient to use an array.
- (NSString *)theFunction:(float)input {
NSArray * array = [[NSArray alloc] initWithObjects: #"",#"",#"1/8",#"",#"1/4",#"",#"3/8",#"",#"1/2",#"",#"5/8",#"",#"3/4",#"",#"3/4",#"",#"7/8",#"",nil];
int fractions = lroundf((input - (int)input)/((float)1/(float)16));
if(fractions == 0 || fractions == 16) {
return [NSString stringWithFormat:#"%d",lroundf(input)];
} else {
if([[array objectAtIndex:fractions] isEqualToString:#""]) {
return [NSString stringWithFormat:#"%d %d/16",(int)input,fractions];
} else {
return [NSString stringWithFormat:#"%d %#",(int)input,[array objectAtIndex:fractions]];
}
}
}
I think your problem is much simpler than the one #Caleb linked to.
Divide by 0.0625 to get the number of sixteenths. Round the result to the nearest integer i. Use integer division i / 16 to get the number of whole units and use the modulo operator j = i % 16 to get the fractional units. To reduce the fractions, use j as an index into an array you create ahead of time as { "", "1/16", "1/8", "3/16", ... }.
You can also divide by 16 and get the modulo 16 using bitwise operators, but that will make the code harder to read for not much benefit.