trial and error do while statement in iOS - objective-c

I am new to iOS programming/objective c, I am trying to do an iterative trial and error calculation and I am stuck. Ordinarily this code would have worked in excel VBA so I'm not sure how to overcome this issue in obj C:
- (IBAction)calculate:(id)sender {
static float friction=2;
static float difference;
float Re = [pipe_id.text floatValue] * [fluid_velocity.text floatValue] / [kin_viscosity.text floatValue];
ReynoldsNo.text = [[NSString alloc]initWithFormat:#"%6.2f", Re];
do{
float Colebrook1 = 1/powf(friction,0.5);
float Colebrook2 = -2*log10f([RelativeRoughness.text floatValue]/(3.7*[pipe_id.text floatValue]) + 2.51/(Re*powf(friction,0.5)));
float difference = fabsf((Colebrook1-Colebrook2)*1000);
friction = friction - 0.000001;
FrictionFactor.text = [[NSString alloc]initWithFormat:#"%6.2f", friction];
Cole1.text = [[NSString alloc]initWithFormat:#"%6.2f", Colebrook1];
Cole2.text = [[NSString alloc]initWithFormat:#"%6.2f", Colebrook2];
}while (difference > 0.000001);
}
So when I compile this, the value for friction stays at 2. My loop isn't working, so the whole trial and error thing has fallen apart. I need some help to see how this should be written in objective C. Thanks for you help, ALM.

This line is your problem:
float difference = fabsf((Colebrook1-Colebrook2)*1000);
You already declare the variable difference outside the loop; there is no need to declare it again inside the loop.
You probably want to say:
difference = fabsf((Colebrook1-Colebrook2)*1000);
Also, are you sure that your outer declaration needs to be static? That means its value persists between calls to the method. It's valid code, but unusual to see.

Be aware of block scope. Your inner difference shadows the outer, so you may want to avoid re-declaring it by simply removing the float.
Also, as a convention tip, leave the capitalized identifiers for classes.

Related

Converting a string variable from Binary to Decimal in Objective C

Im trying to create a Binary to Decimal calculator and I am having trouble doing any sort of conversion that will actually work. First off Id like to introduce myself as a complete novice to objective c and to programming in general. As a result many concepts will appear difficult to me, so I am mostly looking for the easiest way to understand and not the most efficient way of doing this.
I have at the moment a calculator that will accept input and display this in a label. This part is working fine and I have no issues with it. The variable that the input is stored on is _display = [[NSMutableString stringWithCapacity:20] retain];
this is working perfectly and I am able to modify the data accordingly. What I would like to do is to be able to display an NSString of the conversion in another label. At the moment I have tried a few solutions and have not had any decent results, this is the latest attempt
- (NSMutableString *)displayValue2:(long long)element
{
_str= [[NSMutableString alloc] initWithString:#""];
if(element > 0){
for(NSInteger numberCopy = element; numberCopy > 0; numberCopy >>= 1)
{
[_str insertString:((numberCopy & 1) ? #"1" : #"0") atIndex:0];
}
}
else if(element == 0)
{
[_str insertString:#"0" atIndex:0];
}
else
{
element = element * (-1);
_str = [self displayValue2:element];
[_str insertString:#"0" atIndex:0];
NSLog(#"Prima for: %#",_str);
for(int i=0; i<[_str length];i++)
_str = _display;
NSLog(#"Dopo for: %#",_str);
}
return _str;
}
Within my View Controller I have a convert button setup, when this is pressed I want to set the second display field to the decimal equivalent. This is working as if I set displayValue2 to return a string of my choosing it works. All I need is help getting this conversion to work. At the moment this bit of code has led to "incomplete implementation" being displayed at the to of my class. Please help, and cheers to those who take time out to help.
So basically all you are really looking for is a way to convert binary numbers into decimal numbers, correct? Another way to think of this problem is changing a number's base from base 2 to base 10. I have used functions like this before in my projects:
+ (NSNumber *)convertBinaryStringToDecimalNumber:(NSString *)binaryString {
NSUInteger totalValue = 0;
for (int i = 0; i < binaryString.length; i++) {
totalValue += (int)([binaryString characterAtIndex:(binaryString.length - 1 - i)] - 48) * pow(2, i);
}
return #(totalValue);
}
Obviously this is accessing the binary as a string representation. This works well since you can easily access each value over a number which is more difficult. You could also easily change the return type from an NSNumber to some string literal. This also works for your element == 0 scenario.
// original number wrapped as a string
NSString *stringValue = [NSString stringWithFormat:#"%d", 11001];
// convert the value and get an NSNumber back
NSNumber *result = [self.class convertBinaryStringToDecinalNumber:stringValue];
// prints 25
NSLog(#"%#", result);
If I misunderstood something please clarify, if you do not understand the code let me know. Also, this may not be the most efficient but it is simple and clean.
I also strongly agree with Hot Licks comment. If you are truly interested in learning well and want to be an developed programmer there are a few basics you should be learning first (I learned with Java and am glad that I did).

Floating Point things work.....Most of the time [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Correcting floating point numbers
float randNum = arc4random()%(100)-1;
I read somewhere that this will give me random numbers between 1-100. Or something close to that.
This line seems to work all the time, but I convert this number to an NSString for storage/printing to text, and then convert it back to a float for ordering and other calculations. But when I get that float back sometimes it looks something like gibberish; like this in the variable view:
9 float 9.75303731e-41
Why would converting to an NSString and back to a float ruin the float value I'm using? (e.g. What could I have screwed up? Or should I be using CGFloat instead?)
I think this is all the pertinent code:
NSMutableArray *stringArray = [[NSMutableArray alloc] init];
floatArray[30];
// put three random floats into an NSMutableArray of NSStrings
for(int i = 0; i < 3; i++)
{
float randNum = arc4random()%(100)-1;
NSString *randString = [NSString stringWithFormat:#"%.3f", randNum];
[stringArray addObject:randString];
}
// convert NSStrings back to float
for(NSString *string in stringArray)
{
float temp = [string floatValue];
floatArray[iterator] = temp;
}
Thanks in advance for any help/advice.
EDIT: When I step through the code it looks like the float value looks sane until the line "float temp = [string floatValue]", which is where the value seems to be garbaged.
Why are you using float when the result from arc4random() is a uint32_t? Switching to integer types would almost certainly get around all this, as I suspect the problem is because of the conversion to string form allowing only 3 significant digits. What happens if you use %.15f as your format?
Sidenote: use arc4random_uniform() - it's simpler and guaranteed to be a uniformly random distribution within that range.

Is it safe to use pointers to change values in blocks?

I've started using blocks, and one of the first things I encountered is an inability to set values which are captured by the closure. This is fine, I've been using C/C++ a long time. I'll just use pointers!
MyObject* bestObj = nil;
float bestDist= 10000.f;
MyObject **pBestObj = &bestObj;
float* pBestDist = &bestDist;
[self testObjects:class block:^(MyObject* obj){
CGRect r = [obj boundingBox];
// position is captured from outside this code sample
if( CGRectContainsPoint( r, position ) )
{
float dist = GetDistance( obj, position );
if(dist < bestDist)
{
*pBestDist = dist;
*pBestObj = obj;
}
}
}];
return bestObj;
My question is, is this safe? I assume that as long as my pointer points to something that hasn't gone out of scope and that still exists, that it should work. But I'm also assuming that things that take blocks don't ever, say, run them in parallel. I know my code doesn't, but I don't know about, say, using a block with an NSArray enumerateObjectsUsingBlock call.
The 'right' way to do this would be to mark those original variables as block mutable, __block

Cast an Objective C UITextField value to float

I have a UITextField called txtDiscount
It has a value in it: txtDiscount.text == 2.3 //for example
I've tried:
float test = (NSNumber *)txtDiscount.text;
And it compiles, but at runtime breaks down.
Unacceptable type of value for attribute: property = ..."; desired type = NSNumber; given type = NSCFString; value = .
How can I cast the value?
Any help greatly appreciated,
Thanks // :)
You probably want something like:
float test = [txtDiscount.text floatValue];
The NSString documentation provides a list of all the built-in casts.
A cast like this
(NSNumber *)myInstance
is telling the compiler to treat 'myInstance' as if it were an instance of class NSNumber. This may influence compile time warnings and errors. Note: - the compiler. It makes no difference to the code that is generated or run - at all. The code that you are running is still
float test = [txtDiscount text];
where the method -text is returning a pointer to an NSString and you are trying to assign it to a float variable.
see clee's answer for how to get float value from an NSString - but make sure you understand why what you were trying to do is wrong. It will help loads in the long run.

Objective-C: int value changing without cause

Objective-C: I need help retaining the value of an int. It's changing on me without my command.
The original question was: "How do you declare and retain an int?", that was satisfied in another post here: Objective-C: How do you declare and retain an int?
Now I have a problem where an int that was 18 is changing to 2, somehow on its own.
Here's my code:
#interface Game : Layer // this is from cocos2d
{
int maxSprites;
}
#implementation Game
-(void)initVariables
{
maxSprites = 18;
}
Later on, when I print it out, like
NSLog(#" maxSprites = %d ", maxSprites);
I get:
maxSprites = 2
And operations that require it to be 18, crash or don't work, as if it's really just 2 now.
How would that be possible? =)
Apple + Shift + F reveals no other usage of the maxSprites variable.
I've looked at other code examples and often they're exposing the variable with a getter and setter, and they are also using #property. Am I missing something? I'm new to Objective-C, so I might as well just be!
I did a Apple + Shift + F for maxSprites" In Project, Textual, Contains, Ignore Case and only resulted in:
Game.h: int maxSprites;
Game.m: maxSprites = 18;
Game.m: NSLog(#" maxSprites = %d", maxSprites);
Game.m: NSLog(#" maxSprites = %d", maxSprites);
Game.m: NSLog(#"maxSprites is at %p", &maxSprites);
Game.m: NSLog(#"maxSprites is at %p", &maxSprites);
Game.m: NSLog(#" maxSprites = %d", maxSprites);
Game.m: NSLog(#" maxSprites = %d", maxSprites);
Game.m: NSLog(#"maxSprites is at %p", &maxSprites);
Game.m: NSLog(#"maxSprites is at %p", &maxSprites);
I found the location where it changes using a watchpoint. It changes
Expression: “*(int *) 67379960”
New Value: 2
Old Value: 18
on this line:
[self checkMatchBarAward:spriteTypeToAdd];
Odd? That function doesn't do anything with maxSprites, nor does that line.
EDIT:
here is the function, I commented everything inside it out and it still occurs:
.h
-(void)checkMatchBarAward:(int)spriteTypeToAdd;
.m
-(void)checkMatchBarAward:(int)spriteTypeToAdd
{
}
EDIT:
Thanks for the recommendations. I have cleaned all targets and it still changed values. Because of the answers you guys/gals gave, you lead me to the problem. Thanks for all of your help.
I posted my results below in an answer. Here's a copy:
Guys/gals you wouldn't believe what was the cause. Thank you for all your help because telling me to clean and look and check my types, that helped.
I looked over my arrays. I found one that was declared like this:
int matchBarArray[8];
2 lines up from the breakpoint halt where it says that the value changed from 18 to 2, I have this line:
matchBarArray[spritesCaptured-1] = spriteTypeToAdd;
And guess what, I overstepped the bounds of the array by 1. If I increase the size of the array to 9, I no longer get the int change from 18 to 2.
Also, if I overstep the bounds by more than 1, that is, I reduce the array size to smaller, there are other things that start changing such as my score, booleans, the whole game ! =)
I can't believe hitting memory outside the array in Objective-C can cause such a riot =) AND IT'S SO HARD TO DEBUG!
Guys/gals, you wouldn't believe what was the cause. Thank you for all your help because telling me to clean and look and check my types, that helped.
I looked over my arrays. I found one that was declared like this:
int matchBarArray[8];
2 lines up from the breakpoint halt where it says that the value changed from 18 to 2, I have this line:
matchBarArray[spritesCaptured-1] = spriteTypeToAdd;
And guess what, I overstepped the bounds of the array by 1. If I increase the size of the array to 9, I no longer get the int change from 18 to 2.
Also, if I overstep the bounds by more than 1, that is, I reduce the array size to smaller, there are other things that start changing such as my score, booleans, the whole game ! =)
I can't believe hitting memory outside the array in Objective-C can cause such a riot =) AND IT'S SO HARD TO DEBUG!
If your checkMatchBarAward: method truly is empty, then you need to clean your project (Shift + cmd + k) and rebuild it.
I didn't see the line you specify in your code.
Chances are, though, that you are referring to something as a long* when it's an int* or something like that (although how, after all these years, C STILL can't see that is beyond me).
Anyway, check your types where the sizes of what they point to may differ. If you reference an int * memory location with a long * (say, by passing in an int* to a method that expects a long*), you will fubar the stack and start modifying adjacent variables.
I've done this more than once, but in C, not Objective C--so I'm not sure it's the correct answer.