Objective C: Comparison issue between numbers - objective-c

I am trying to implement the code snippet below. However I am unable to get my expected results. For example if my disanceFromLoc = 0.16, I am still getting my output as 0.16 km.
Is there something wrong with the way I am comparing the value? object is of 'NSNumber' class (defined it as double in core data)
if ([object.distanceFromLoc doubleValue] < 0)
{
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Approx. Distance: %0.2f m", [object.distanceFromLoc doubleValue]*1000];
}
else
{
cell.detailTextLabel.text = [[NSString alloc] initWithFormat:#"Approx. Distance: %0.2f km", [object.distanceFromLoc doubleValue]];
}
Thanks!
Zhen Hoe

I believe you mean to compare to one, not zero.
As it stands, you're checking if your distanceFromLoc is negative, which (presumably) never happens with a regular distance. Instead, you should be checking if you're closer than 1km (i.e. < 1), at which point you can multiply by 1000 and convert to meters.

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).

iTunes Search API, finding Free prices

When searching the iTunes store, I've hit a little problem. I'm trying to change the text of my label to "FREE" when the price is 0.00, as opposed to displaying the price. The problem is, my comparison of the two NSDecimalNumbers fails. Here's where I am currently at.
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
[formatter setCurrencyCode:self.searchResult.currency];
NSString *price = [formatter stringFromNumber:self.searchResult.price];
NSDecimalNumber *free = [[NSDecimalNumber alloc] initWithFloat:0.00f];
NSLog(#"Price:%#",price);
NSLog(#"Free:%#",free);
NSLog(#"self.searchResult.price: %#", self.searchResult.price);
if (self.searchResult.price == free) {
NSString *freeText = [NSString stringWithFormat:#"FREE"];
self.priceLabel.text = freeText;
}
else {
self.priceLabel.text = price;
}
NSLog(#"priceLabel:%#", self.priceLabel.text);
What's really weird is that the Console even says that both free and del.searchResult.price are the same:
2012-11-24 20:01:16.178 StoreSearch[1987:c07] Price:$0.00
2012-11-24 20:01:16.178 StoreSearch[1987:c07] Free:0
2012-11-24 20:01:16.178 StoreSearch[1987:c07] self.searchResult.price: 0
2012-11-24 20:01:16.179 StoreSearch[1987:c07] priceLabel:$0.00
I'm a little confused by this to be frank. Any help would be appreciated. If you could explain why this has happened so that I can learn not to do it again, then I'd be even more grateful!
Regards,
Mike
you got NSNumber and another NSNumber (NSDecimalNumber) and you do a pointer equal check you either need need to call isEqual or compare the primitive float values
== with objects doesnt compare the value but the object pointer (the memory address)
if(searchResult.price.floatValue == free.floatValue)
note that a float is inprecise and generally should not be used for any calculation or comparison. It is ok in this case though

iOS: NSString variable returning null

I am probably missing something obvious (still learning about Objective-C!) but for some reason one of my NSString variables has a null value in my if statement and I don't know why?
I have even output to NSLog and I still can't see why it's behaving like this.
Basically, the user enters an amount in a text field (itemWeight) and this if statement validates the input and displays an alert according to the result. The problem only seems to be when 0.751 is entered, if you enter any other amount (0.750, 0.749, 0.752, 0.753 and so on) it works as expected.
Relevant code samples as follows...
.h file:
#property (strong, nonatomic) IBOutlet UITextField *itemWeight;
.m file:
NSString *rawWeightText = itemWeight.text;
float convertedWeightText = rawWeightText.floatValue;
NSString *weightMessage;
if (convertedWeightText <= 0.750)
{
weightMessage = #"under 0.750";
}
else if (convertedWeightText >= 0.751)
{
weightMessage = #"0.751 or over";
}
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: #"Error"
message: weightMessage
delegate: nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
Any ideas where I'm going wrong/what I've forgotten to do would be much appreciated, thank you!
Looking at the condition of your if-else if code does not have the range of from 0.750 to 0.751.
floating-point values ​​must be careful to compare. you should consider about 0.751 possibility 0.75099999...
the following loop, the result is 99.999046, not 100. Continue to add more accuracy is poor.
float a= 0.1f;
float result = 0.f;
for(int i = 0; i<1000; i++)
{
result += 0.1f;
}
printf("result:%f", result); //99.999046
So, In General, Comparison of these expressions is not recommended.
if (result == expectedResult)
Writing the following method is recommended to compare.
bool AlmostEqualRelative(float A, float B, float maxRelativeError)
{
if (A == B)
return true;
float relativeError = fabs((A - B) / B);
if (relativeError <= maxRelativeError)
return true;
return false;
}
For more information, please read here
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
also, you must read this wiki:
http://en.wikipedia.org/wiki/Floating_point
http://en.wikipedia.org/wiki/Denormal_number
Decimal values often can't be exactly represented in binary. When the user enters 0.751, its likely that the actual float that you get back is slightly smaller, like 0.750999942. Try logging the value to see what's going on.
You are not the first programmer who is surprised by the actual behavior of floating point numbers.
In fact it is more a problem with binary decimal numbers, then the floating point details.
Try to convert 0.751, which has only 3 digits in the fractional part, into a binary number and you'll see.
To make it short, 0.751 is represented as a binary exponent of -1 and a mantissa of 1.10000000100000110001001 in a float (float only has 23+1 bits of precision for the mantissa).
That is, in decimal, an exponent of -1 and a mantissa of 1.5019999742507935.
Therefore 2^-1 * 1.5019999742507935 = 0.7509999871254 and it does not pass the test in the if.

parsing string into different kind of number string

I have a string called realEstateWorth with a value of $12,000,000.
I need this same string to remain a string but for any number (such as the one above) to be displayed as $12 MILLION or $6 MILLION. The point is it needs the words "MILLION" to come after the number.
I know there is nsNumberFormatter that can convert strings into numbers and vice versa but can it do what I need?
If anyone has any ideas or suggestions, it would be much appreciated.
Thank you!
So as I see it, you have two problems:
You have a string representation of something that's actually a number
You (potentially) have a number that you want formatted as a string
So, problem #1:
To convert a string into a number, you use an NSNumberFormatter. You've got a pretty simple case:
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterCurrencyStyle];
NSNumber *n = [f numberFromString:#"$12,000,000"];
// n is 12000000
That was easy! Now problem #2:
This is trickier, because you want a mixed spell-out style. You could consider using an NSNumberFormatter again, but it's not quite right:
[f setNumberStyle:NSNumberFormatterSpellOutStyle];
NSString *s = [f stringFromNumber:n];
// s is "twelve million"
So, we're closer. At this point, you could perhaps maybe do something like:
NSInteger numberOfMillions = [n integerValue] / 1000000;
if (numberOfMillions > 0) {
NSNumber *millions = [NSNumber numberWithInteger:numberOfMillions];
NSString *numberOfMillionsString = [f stringFromNumber:millions]; // "twelve"
[f setNumberStyle:NSNumberFormatterCurrencyStyle];
NSString *formattedMillions = [f stringFromNumber:millions]; // "$12.00"
if ([s hasPrefix:numberOfMillionsString]) {
// replace "twelve" with "$12.00"
s = [s stringByReplacingCharactersInRange:NSMakeRange(0, [numberOfMillionsString length]) withString:formattedMillions];
// if this all works, s should be "$12.00 million"
// you can use the -setMaximumFractionDigits: method on NSNumberFormatter to fiddle with the ".00" bit
}
}
However
I don't know how well this would work in anything other than english. CAVEAT IMPLEMENTOR
Worst case scenario, you could implement a category on NSString to implement the behaviour you want.
In the method that you would do in that category you could take an NSNumberFormatter to bring that string to a number and by doing some modulo operation you could define if you need the word Million, or Billion, etc. and put back a string with the modulo for Million or other way you need it to be.
That way you could just call that method on your NSString like this :
NSString *humanReadable = [realEstateWorth myCustomMethodFromMyCategory];
And also.
NSString are immutable, so you can't change it unless you assign a new one to your variable.
I'd recommend storing this value as an NSNumber or a float. Then you could have a method to generate an NSString to display it like:
- (NSString*)numberToCurrencyString:(float)num
{
NSString *postfix = #"";
if (num > 1000000000)
{
num = num / 1000000000;
postfix = #" Billion";
}
else if (num > 1000000)
{
num = num / 1000000;
postfix = #" Million";
}
NSString *currencyString = [NSString stringWithFormat:#"%.0f%#", num, postfix];
return currencyString;
}
Note: Your question states that your input needs to remain a string. That's fine. So you'd need to 1.) first parse the number out of the string and 2.) then reconvert it to a string from a number. I've shown how to do step 2 of this process.

Objective-C Condtions operators weirdness

Okay here's the damned thing:
- (void)setMinimumNumberOfSides:(NSNumber *)newMinimumNumberOfSides {
if (newMinimumNumberOfSides != minimumNumberOfSides) {
NSNumber *minimum = [[NSNumber alloc] initWithInt:(int)2];
if (newMinimumNumberOfSides > minimum) {
[newMinimumNumberOfSides retain];
[minimumNumberOfSides release];
minimumNumberOfSides = newMinimumNumberOfSides;
} else {
NSLog(#"setMinimumNumberOfSides: Invalid number of sides: %# is smaller than the minimum of %# allowed.",
newMinimumNumberOfSides, minimum);
}
[minimum release];
[newMinimumNumberOfSides release];
}
}
There's something weird going on in there! The problem is my if (newMinimumNumberOfSides > minimum) {} condition. Even if newMinimumNumberOfSides is greated than minimum it goes into the else statement.
I did:
NSNumber *minimum = [[NSNumber alloc] initWithInt:(int)6];
[polygon setMinimumNumberOfSides:minimum];
which is way greater than 2. And I receive my error message...
I tried to NSLog those two, and it gives me the right numbers... So what's going on with this?
Thanks a lot!
I think you need to change your if statement to:
if ([newMinimumNumberOfSides intValue] > [minimum intValue])
NSNumber is an object, so you have to get its integer value before you can start using it in comparisons.
You need to use the following method to compare NSNumber objects:
- (NSComparisonResult)compare:(NSNumber *)aNumber
but better yet just convert them to c ints: [myNSNumberValue inValue]