Adding a decimal point button to an iOS Calculator - objective-c

I followed a tutorial to make an iOS Calculator, and I am now wanting to add a decimal place button to it. Here is my code
header file:
#import <UIKit/UIKit.h>
#interface CalcViewController : UIViewController {
float result;
float selectedNumber;
int selectedOperation;
IBOutlet UILabel *calcScreen;
}
-(IBAction)numberPressed:(id)sender;
-(IBAction)operationPressed:(id)sender;
-(IBAction)clearNumber:(id)sender;
-(IBAction)clearOperation:(id)sender;
#end
Here is my implementation file
#import "CalcViewController.h"
#implementation CalcViewController
-(IBAction)numberPressed:(id)sender {
selectedNumber = selectedNumber * 10 + (float) [sender tag];
calcScreen.text = [NSString stringWithFormat:#"%2g", selectedNumber];
}
-(IBAction)operationPressed:(id)sender {
if (selectedOperation == 0) {
result = selectedNumber;
} else {
switch (selectedOperation) {
case 1:
result = result + selectedNumber;
break;
case 2:
result = result - selectedNumber;
break;
case 3:
result = result * selectedNumber;
break;
case 4:
result = result / selectedNumber;
break;
case 5:
selectedOperation = 0;
break;
}
}
selectedNumber = 0;
calcScreen.text = [NSString stringWithFormat:#"%2g", result];
if ([sender tag] == 0) result = 0;
selectedOperation = [sender tag];
}
-(IBAction)clearNumber:(id)sender {
selectedNumber = 0;
calcScreen.text = #"0";
}
-(IBAction)clearOperation:(id)sender {
selectedNumber = 0;
calcScreen.text = #"0";
selectedOperation = 0;
}
I saw on another thread that someone had suggesting using the method:
- (IBAction)Decimal:(id)sender
{
NSString *currentText = calcScreen.text;
if ([currentText rangeOfString:#"." options:NSBackwardsSearch].length == 0) {
calcScreen.text = [calcScreen.text stringByAppendingString:#"."];
}
However this did not seem to work for me. It would indeed let me enter a decimal point, but when a second number was entered the decimal point would be lost. Can anyone suggest a method I could implement to achieve what I am trying to?
Cheers in advance!

My quick thought: keep the number as text on the screen, adding additional digits and/or decimal point to it as text. Only convert it to a float (I would use double myself, btw) at the moment that an operation is performed. The suggested method should then work fine.
Something like:
-(IBAction)numberPressed:(id)sender {
calcScreen.text = [calcScreen.text stringByAppendingString:[sender tag]];
}
-(IBAction)operationPressed:(id)sender {
selectedNumber = [calcScreen.text floatValue];
...
}

One quick tip, instead of using
int selectedOperation;... and later in code
switch (selectedOperation) {
case 1:
result = result + selectedNumber;
break;
case 2:
result = result - selectedNumber;
...
Try using typedef enum
typedef enum {
OperationTypeAdd = 0,
OperationTypeSub,
...
} OperationType
and in switch block
switch (operationType) {
case OperationTypeAdd:
result = result + selectedNumber;
break;
case operationTypeSub:
result = result - selectedNumber;
break;

Related

Can I get the number of a case statement in Objective-C?

I have a switch statement like this:
switch (int) {
case 0:
// do x
break;
case 1:
// do y
break;
default:
break;
}
Can I get the case number?
The reason I ask is that I have a method in each one that would use a variable int. For example:
switch (int) {
case 0:
[self doMethod:string setTag: <CASE NUMBER> ];
break;
case 1:
[self doMethod:string setTag: <CASE NUMBER> ];
break;
default:
break;
}
Is there any way to do this?
Thanks!
switch (x) {
case 0:
// if you're here, you know x == 0
[self doMethod:string setTag: x];
break;
...
}
But unless string is a different variable or literal in each case, this doesn't make much sense; you could as easily say
if (x == 0 || x == 1) {
[self doMethod: string setTag: x];
}
First off, you can't do switch (int). int is a data type. You need a variable in there.
Then all you need to do is reference the variable in the case statement:
int someVar = ... // some value
switch (someVar) {
case 0:
[self doMethod:string setTag:someVar];
break;
case 1:
[self doMethod:string setTag:someVar];
break;
}
BTW - if you do the same thing for multiple cases you can do:
int someVar = ... // some value
switch (someVar) {
case 0:
case 1:
[self doMethod:string setTag:someVar];
break;
default:
// other stuff
break;
}
And as Josh pointed out, depending on your needs, this whole thing could simply be:
int someVar = ... // some value
[self doMethod:string setTag:someVar];
or maybe:
int someVar = ... // some value
if (someVar >= 0 && someVar <= 1) {
[self doMethod:string setTag:someVar];
}

Adding Alpha-Beta prunning to minMax in Objective-C

Hi there I have problems adding alpha beta pruning to my minMax algorithm for the connect 4 game can you help me ? here is my code for the minMax procedure, it looks to me that there is just a little that have to be done what eludes me :S scoreBoard() is my Heuristics function and I returning an array with 2 values the first one is the position of on the table and the other one is the score for this position.
-(NSArray*) miniMaxWihtAlphaBetaPrunning:(BOOL)maxOrMin withAlpha:(NSInteger)alpha
withBeta:(NSInteger)beta withPlayer:(enum playerColor)player andTreeDepth:
(NSInteger)depth
{
if (depth == 0)
{
return [NSArray arrayWithObjects:[NSNumber numberWithInt:-1],
[NSNumber numberWithInt:scoreBoard()],nil];
}
else
{
NSInteger bestScore = maxOrMin ? redWins: blueWins;
NSInteger bestMove = -1;
for (NSInteger column = 0; column < 10; column++)
{
if (discPlacedMatrix[0][column] != 0)
{
continue;
}
NSInteger rowFilled = dropDiscAtPoint(column, player);
if (rowFilled == -1)
{
continue;
}
NSInteger s = scoreBoard();
if (s == (maxOrMin? blueWins : redWins))
{
bestMove = column;
bestScore = s;
discPlacedMatrix[rowFilled][column] = 0;
break;
}
NSArray* result = [NSArray arrayWithArray:[self miniMaxWihtAlphaBetaPrunning:!maxOrMin withAlpha:alpha withBeta:beta withPlayer:(player == 1 ? RED : BLUE) andTreeDepth:depth - 1]];
NSInteger scoreInner = [[result objectAtIndex:1] intValue];
discPlacedMatrix[rowFilled][column] = 0;
if (scoreInner == blueWins || scoreInner == redWins)
{
scoreInner -= depth * player;
}
if (maxOrMin)
{
if (scoreInner >= bestScore)
{
bestScore = scoreInner;
bestMove = column;
}
}
else
{
if (scoreInner <= bestScore)
{
bestScore = scoreInner;
bestMove = column;
}
}
}
return [NSArray arrayWithObjects:[NSNumber numberWithInt:bestMove],[NSNumber numberWithInt:bestScore],nil];
}
}
I tried some scenarios but the Ai started to
It sounds like you're looking for something like the jamboree algorithm. The basic idea of this algorithm is to go through your tree recursively, and at each level, run the alpha beta algorithm on part of the nodes at that level, and then run the mini-max algorithm on the rest of the nodes. I'm at work right now, but I'll elaborate when I get home.
An implementation:
http://chessprogramming.wikispaces.com/Jamboree

extracting variable from one method to another method in the same .m file in objective c, xcode

Hello I would like to know how to use a variable from this method
+ (NSString *) yourCalculation:(NSString *)height:(NSString *)weight{
double bmiVal = 0;
if (weight > 0 && height > 0) {
CGFloat wInPounds = [weight floatValue];
CGFloat hInInches = [height floatValue];
CGFloat hInCms = hInInches *0.393700787;
}
}
in this method
+(NSString *) actualCalculation{
float val = wInPounds/(hInCms*hInCms);
float bmiVal = val *703;
}
This is only a small segment of the code, but it gets across what I want to do with it.
If anyone can tell me how to do this, I would appreciate it.
Thanking You
Create a custom class that has properties for the various values you want to share and return an instance of that. For example, assuming a MyNumerics class with the obvious properties:
+ (MyNumerics *) yourCalculation:(NSString *)height weight:(NSString *)weight {
MyNumerics *result = nil;
double bmiVal = 0;
if (weight > 0 && height > 0) {
result = [[MyNumerics alloc] init];
result.wInPounds = [weight floatValue];
result.hInInches = [height floatValue];
result.hInCms = hInInches *0.393700787;
}
return result;
}
Have the calling routine use the result's properties in its calculations.

UIColor comparison

Given a UIColor, I need to determine if it is "light" or "dark". If I could access the hex value of the color, I could just check if it was greater than or less than a certain threshold hex number, but there appears to be no way to do that. Is there? Or is there another way I could check the brightness value of a UIColor?
You could install this Category for extending UIColor for knowing HSV/HSB and compare [aUIColor brightness]
Edit:
I found the same code in some github-hosted project, made a gist of it: https://gist.github.com/1252197
#import "UIColor-HSVAdditions.h"
#implementation UIColor (UIColor_HSVAdditions)
+(struct hsv_color)HSVfromRGB:(struct rgb_color)rgb
{
struct hsv_color hsv;
CGFloat rgb_min, rgb_max;
rgb_min = MIN3(rgb.r, rgb.g, rgb.b);
rgb_max = MAX3(rgb.r, rgb.g, rgb.b);
hsv.val = rgb_max;
if (hsv.val == 0) {
hsv.hue = hsv.sat = 0;
return hsv;
}
rgb.r /= hsv.val;
rgb.g /= hsv.val;
rgb.b /= hsv.val;
rgb_min = MIN3(rgb.r, rgb.g, rgb.b);
rgb_max = MAX3(rgb.r, rgb.g, rgb.b);
hsv.sat = rgb_max - rgb_min;
if (hsv.sat == 0) {
hsv.hue = 0;
return hsv;
}
if (rgb_max == rgb.r) {
hsv.hue = 0.0 + 60.0*(rgb.g - rgb.b);
if (hsv.hue < 0.0) {
hsv.hue += 360.0;
}
} else if (rgb_max == rgb.g) {
hsv.hue = 120.0 + 60.0*(rgb.b - rgb.r);
} else /* rgb_max == rgb.b */ {
hsv.hue = 240.0 + 60.0*(rgb.r - rgb.g);
}
return hsv;
}
-(CGFloat)hue
{
struct hsv_color hsv;
struct rgb_color rgb;
rgb.r = [self red];
rgb.g = [self green];
rgb.b = [self blue];
hsv = [UIColor HSVfromRGB: rgb];
return (hsv.hue / 360.0);
}
-(CGFloat)saturation
{
struct hsv_color hsv;
struct rgb_color rgb;
rgb.r = [self red];
rgb.g = [self green];
rgb.b = [self blue];
hsv = [UIColor HSVfromRGB: rgb];
return hsv.sat;
}
-(CGFloat)brightness
{
struct hsv_color hsv;
struct rgb_color rgb;
rgb.r = [self red];
rgb.g = [self green];
rgb.b = [self blue];
hsv = [UIColor HSVfromRGB: rgb];
return hsv.val;
}
-(CGFloat)value
{
return [self brightness];
}
#end
[UIColor CGColor] will get you a CGColorRef, from there you can do CGColorGetComponents to get the individual components. Getting the "brightness" value depends on your definition of brightness. Getting an average of the components (in case of RGB color space) might be a good start.
UIColor (and CGColorRef) are generally described in RGB values. If you want to determine light or dark, you'll probably want to convert these values to something like Hue/Saturation/Brightness. But there are no built in functions like you are looking for.
here is a guide (with code provided) on UIColor expansion (using a category) and has methods such as get hexStringFromColor: It should be what you're looking for. UIColor expansion Note: I did not write this blog or code.
Proposed algorithm to calculate color / color brightness difference: http://maestric.com/doc/color_brightness_difference_calculator
(based on w3c paper)

Compare version numbers in Objective-C

I am writing an application that receives data with items and version numbers. The numbers are formatted like "1.0.1" or "1.2.5". How can I compare these version numbers? I think they have to be formatted as a string first, no? What options do I have to determine that "1.2.5" comes after "1.0.1"?
This is the simplest way to compare versions, keeping in mind that "1" < "1.0" < "1.0.0":
NSString* requiredVersion = #"1.2.0";
NSString* actualVersion = #"1.1.5";
if ([requiredVersion compare:actualVersion options:NSNumericSearch] == NSOrderedDescending) {
// actualVersion is lower than the requiredVersion
}
I'll add my method, which compares strictly numeric versions (no a, b, RC etc.) with any number of components.
+ (NSComparisonResult)compareVersion:(NSString*)versionOne toVersion:(NSString*)versionTwo {
NSArray* versionOneComp = [versionOne componentsSeparatedByString:#"."];
NSArray* versionTwoComp = [versionTwo componentsSeparatedByString:#"."];
NSInteger pos = 0;
while ([versionOneComp count] > pos || [versionTwoComp count] > pos) {
NSInteger v1 = [versionOneComp count] > pos ? [[versionOneComp objectAtIndex:pos] integerValue] : 0;
NSInteger v2 = [versionTwoComp count] > pos ? [[versionTwoComp objectAtIndex:pos] integerValue] : 0;
if (v1 < v2) {
return NSOrderedAscending;
}
else if (v1 > v2) {
return NSOrderedDescending;
}
pos++;
}
return NSOrderedSame;
}
This is an expansion to Nathan de Vries answer to address the problem of 1 < 1.0 < 1.0.0 etc.
First off we can address the problem of extra ".0"'s on our version string with an NSString category:
#implementation NSString (VersionNumbers)
- (NSString *)shortenedVersionNumberString {
static NSString *const unnecessaryVersionSuffix = #".0";
NSString *shortenedVersionNumber = self;
while ([shortenedVersionNumber hasSuffix:unnecessaryVersionSuffix]) {
shortenedVersionNumber = [shortenedVersionNumber substringToIndex:shortenedVersionNumber.length - unnecessaryVersionSuffix.length];
}
return shortenedVersionNumber;
}
#end
With the above NSString category we can shorten our version numbers to drop the unnecessary .0's
NSString* requiredVersion = #"1.2.0";
NSString* actualVersion = #"1.1.5";
requiredVersion = [requiredVersion shortenedVersionNumberString]; // now 1.2
actualVersion = [actualVersion shortenedVersionNumberString]; // still 1.1.5
Now we can still use the beautifully simple approach proposed by Nathan de Vries:
if ([requiredVersion compare:actualVersion options:NSNumericSearch] == NSOrderedDescending) {
// actualVersion is lower than the requiredVersion
}
I made it myself,use Category..
Source..
#implementation NSString (VersionComparison)
- (NSComparisonResult)compareVersion:(NSString *)version{
NSArray *version1 = [self componentsSeparatedByString:#"."];
NSArray *version2 = [version componentsSeparatedByString:#"."];
for(int i = 0 ; i < version1.count || i < version2.count; i++){
NSInteger value1 = 0;
NSInteger value2 = 0;
if(i < version1.count){
value1 = [version1[i] integerValue];
}
if(i < version2.count){
value2 = [version2[i] integerValue];
}
if(value1 == value2){
continue;
}else{
if(value1 > value2){
return NSOrderedDescending;
}else{
return NSOrderedAscending;
}
}
}
return NSOrderedSame;
}
Test..
NSString *version1 = #"3.3.1";
NSString *version2 = #"3.12.1";
NSComparisonResult result = [version1 compareVersion:version2];
switch (result) {
case NSOrderedAscending:
case NSOrderedDescending:
case NSOrderedSame:
break;
}
Sparkle (the most popular software update framework for MacOS) has a SUStandardVersionComparator class that does this, and also takes into account build numbers and beta markers. I.e. it correctly compares 1.0.5 > 1.0.5b7 or 2.0 (2345) > 2.0 (2100). The code only uses Foundation, so should work fine on iOS as well.
Check out my NSString category that implements easy version checking on github; https://github.com/stijnster/NSString-compareToVersion
[#"1.2.2.4" compareToVersion:#"1.2.2.5"];
This will return a NSComparisonResult which is more accurate then using;
[#"1.2.2" compare:#"1.2.2.5" options:NSNumericSearch]
Helpers are also added;
[#"1.2.2.4" isOlderThanVersion:#"1.2.2.5"];
[#"1.2.2.4" isNewerThanVersion:#"1.2.2.5"];
[#"1.2.2.4" isEqualToVersion:#"1.2.2.5"];
[#"1.2.2.4" isEqualOrOlderThanVersion:#"1.2.2.5"];
[#"1.2.2.4" isEqualOrNewerThanVersion:#"1.2.2.5"];
Swift 2.2 Version :
let currentStoreAppVersion = "1.10.2"
let minimumAppVersionRequired = "1.2.2"
if currentStoreAppVersion.compare(minimumAppVersionRequired, options: NSStringCompareOptions.NumericSearch) ==
NSComparisonResult.OrderedDescending {
print("Current Store version is higher")
} else {
print("Latest New version is higher")
}
Swift 3 Version :
let currentStoreVersion = "1.1.0.2"
let latestMinimumAppVersionRequired = "1.1.1"
if currentStoreVersion.compare(latestMinimumAppVersionRequired, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedDescending {
print("Current version is higher")
} else {
print("Latest version is higher")
}
I thought I'd just share a function I pulled together for this. It is not perfect at all. Please take a look that the examples and results. But if you are checking your own version numbers (which I have to do to manage things like database migrations) then this may help a little.
(also, remove the log statements in the method, of course. those are there to help you see what it does is all)
Tests:
[self isVersion:#"1.0" higherThan:#"0.1"];
[self isVersion:#"1.0" higherThan:#"0.9.5"];
[self isVersion:#"1.0" higherThan:#"0.9.5.1"];
[self isVersion:#"1.0.1" higherThan:#"1.0"];
[self isVersion:#"1.0.0" higherThan:#"1.0.1"];
[self isVersion:#"1.0.0" higherThan:#"1.0.0"];
// alpha tests
[self isVersion:#"1.0b" higherThan:#"1.0a"];
[self isVersion:#"1.0a" higherThan:#"1.0b"];
[self isVersion:#"1.0a" higherThan:#"1.0a"];
[self isVersion:#"1.0" higherThan:#"1.0RC1"];
[self isVersion:#"1.0.1" higherThan:#"1.0RC1"];
Results:
1.0 > 0.1
1.0 > 0.9.5
1.0 > 0.9.5.1
1.0.1 > 1.0
1.0.0 < 1.0.1
1.0.0 == 1.0.0
1.0b > 1.0a
1.0a < 1.0b
1.0a == 1.0a
1.0 < 1.0RC1 <-- FAILURE
1.0.1 < 1.0RC1 <-- FAILURE
notice that alpha works but you have to be very careful with it. once you go alpha at some point you cannot extend that by changing any other minor numbers behind it.
Code:
- (BOOL) isVersion:(NSString *)thisVersionString higherThan:(NSString *)thatVersionString {
// LOWER
if ([thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedAscending) {
NSLog(#"%# < %#", thisVersionString, thatVersionString);
return NO;
}
// EQUAL
if ([thisVersionString compare:thatVersionString options:NSNumericSearch] == NSOrderedSame) {
NSLog(#"%# == %#", thisVersionString, thatVersionString);
return NO;
}
NSLog(#"%# > %#", thisVersionString, thatVersionString);
// HIGHER
return YES;
}
My iOS library AppUpdateTracker contains an NSString category to perform this sort of comparison. (Implementation is based off DonnaLea's answer.)
Usage would be as follows:
[#"1.4" isGreaterThanVersionString:#"1.3"]; // YES
[#"1.4" isLessThanOrEqualToVersionString:#"1.3"]; // NO
Additionally, you can use it to keep track of your app's installation/update status:
[AppUpdateTracker registerForAppUpdatesWithBlock:^(NSString *previousVersion, NSString *currentVersion) {
NSLog(#"app updated from: %# to: %#", previousVersion, currentVersion);
}];
[AppUpdateTracker registerForFirstInstallWithBlock:^(NSTimeInterval installTimeSinceEpoch, NSUInteger installCount) {
NSLog(#"first install detected at: %f amount of times app was (re)installed: %lu", installTimeSinceEpoch, (unsigned long)installCount);
}];
[AppUpdateTracker registerForIncrementedUseCountWithBlock:^(NSUInteger useCount) {
NSLog(#"incremented use count to: %lu", (unsigned long)useCount);
}];
Here is the swift 4.0 + code for version comparison
let currentVersion = "1.2.0"
let oldVersion = "1.1.1"
if currentVersion.compare(oldVersion, options: NSString.CompareOptions.numeric) == ComparisonResult.orderedDescending {
print("Higher")
} else {
print("Lower")
}
Glibc has a function strverscmp and versionsort… unfortunately, not portable to the iPhone, but you can write your own fairly easily. This (untested) re-implementation comes from just reading the documented behavior, and not from reading Glibc's source code.
int strverscmp(const char *s1, const char *s2) {
const char *b1 = s1, *b2 = s2, *e1, *e2;
long n1, n2;
size_t z1, z2;
while (*b1 && *b1 == *b2) b1++, b2++;
if (!*b1 && !*b2) return 0;
e1 = b1, e2 = b2;
while (b1 > s1 && isdigit(b1[-1])) b1--;
while (b2 > s2 && isdigit(b2[-1])) b2--;
n1 = strtol(b1, &e1, 10);
n2 = strtol(b2, &e2, 10);
if (b1 == e1 || b2 == e2) return strcmp(s1, s2);
if (n1 < n2) return -1;
if (n1 > n2) return 1;
z1 = strspn(b1, "0"), z2 = strspn(b2, "0");
if (z1 > z2) return -1;
if (z1 < z2) return 1;
return 0;
}
If you know each version number will have exactly 3 integers separated by dots, you can parse them (e.g. using sscanf(3)) and compare them:
const char *version1str = "1.0.1";
const char *version2str = "1.2.5";
int major1, minor1, patch1;
int major2, minor2, patch2;
if(sscanf(version1str, "%d.%d.%d", &major1, &minor1, &patch1) == 3 &&
sscanf(version2str, "%d.%d.%d", &major2, &minor2, &patch2) == 3)
{
// Parsing succeeded, now compare the integers
if(major1 > major2 ||
(major1 == major2 && (minor1 > minor2 ||
(minor1 == minor2 && patch1 > patch2))))
{
// version1 > version2
}
else if(major1 == major2 && minor1 == minor2 && patch1 == patch2)
{
// version1 == version2
}
else
{
// version1 < version2
}
}
else
{
// Handle error, parsing failed
}
To check the version in swift you can use following
switch newVersion.compare(currentversion, options: NSStringCompareOptions.NumericSearch) {
case .OrderedDescending:
println("NewVersion available ")
// Show Alert Here
case .OrderedAscending:
println("NewVersion Not available ")
default:
println("default")
}
Hope it might be helpful.
Here is a recursive function that do the works with multiple version formatting of any length. It also works for #"1.0" and #"1.0.0"
static inline NSComparisonResult versioncmp(const NSString * a, const NSString * b)
{
if ([a isEqualToString:#""] && [b isEqualToString:#""]) {
return NSOrderedSame;
}
if ([a isEqualToString:#""]) {
a = #"0";
}
if ([b isEqualToString:#""]) {
b = #"0";
}
NSArray<NSString*> * aComponents = [a componentsSeparatedByString:#"."];
NSArray<NSString*> * bComponents = [b componentsSeparatedByString:#"."];
NSComparisonResult r = [aComponents[0] compare:bComponents[0] options:NSNumericSearch];
if(r != NSOrderedSame) {
return r;
} else {
NSString* newA = (a.length == aComponents[0].length) ? #"" : [a substringFromIndex:aComponents[0].length+1];
NSString* newB = (b.length == bComponents[0].length) ? #"" : [b substringFromIndex:bComponents[0].length+1];
return versioncmp(newA, newB);
}
}
Test samples :
versioncmp(#"11.5", #"8.2.3");
versioncmp(#"1.5", #"8.2.3");
versioncmp(#"1.0", #"1.0.0");
versioncmp(#"11.5.3.4.1.2", #"11.5.3.4.1.2");
Based on #nathan-de-vries 's answer, I wrote SemanticVersion.swift for comparing Semantic Version, and here is the test cases.