I have a simple calculator app and I want it to be so that if the answer requires no decimal places, there are none, just whole numbers. If the answer was 2, I don't want it to say 2.000000, it should say 2. If it requires one decimal place, it should show to one decimal place for example 12.8 instead of 12.80. How would I do this? Here is my code.
btw, this is from a tutorial at http://www.youtube.com/watch?v=Ihw0cfNOrr4, not my own work.
viewcontroller.h
#import <UIKit/UIKit.h>
interface calcViewController : UIViewController {
float result;
IBOutlet UILabel *calculatorScreen;
int currentOperation;
float currentNumber;
}
-(IBAction)buttonDigitPressed:(id)sender;
-(IBAction)buttonOperationPressed:(id)sender;
-(IBAction)cancelInput;
-(IBAction)cancelOperation;
#end
in the .m
#import "calcViewController.h"
#implementation calcViewController
-(IBAction)buttonDigitPressed:(id)sender {
currentNumber = currentNumber *10 + (float)[sender tag];
calculatorScreen.text = [NSString stringWithFormat:#"%2f", currentNumber];
}
-(IBAction)buttonOperationPressed:(id)sender {
if (currentOperation ==0) result = currentNumber;
else {
switch (currentOperation) {
case 1:
result = result + currentNumber;
break;
case 2:
result = result - currentNumber;
break;
case 3:
result = result * currentNumber;
break;
case 4:
result = result / currentNumber;
break;
case 5:
currentOperation = 0;
break;
}
}
currentNumber = 0;
calculatorScreen.text = [NSString stringWithFormat:#"%2f", result];
if ([sender tag] ==0) result=0;
currentOperation = [sender tag];
}
-(IBAction)cancelInput {
currentNumber =0;
calculatorScreen.text = #"0";
}
-(IBAction)cancelOperation {
currentNumber = 0;
calculatorScreen.text = #"0";
currentOperation = 0;
}
One way is to use NSNumberFormatter to format your result instead of NSString's -stringWithFormat::
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:requiredDigits];
[formatter setMinimumFractionDigits:0];
NSString *result = [formatter stringFromNumber:[NSNumber numberWithFloat:currentNumber];
The easiest way is just use [[NSNumber numberWithFloat:] stringValue]
Example:
float someFloatValue;
NSString floatWithoutZeroes = [[NSNumber numberWithFloat:someFloatValue] stringValue];
If we use %g in place of %f will truncate all zeros after decimal point.
For example
[NSString stringWithFormat:#"%g", 1.201000];
Output
1.201
This should work
NSString *result = [#(currentNumber) description];
I had the same problem. This is the code snippet that solved it (looks a lot like Caleb's solution, but that one didn't work for me, so I had to add an extra line):
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
numberFormatter.numberStyle = kCFNumberFormatterDecimalStyle;
numberFormatter.maximumFractionDigits = 20;
numberFormatter.minimumFractionDigits = 0;
NSNumber *number = [[NSNumber alloc]init];
NSString *numberString = [numberFormatter stringFromNumber:number];
We can use another numberStyle and override its basic appearance, setting desired properties of an NSNumberFormatter.
Related
Im trying to do the calculations using NSNumbers and keep track of the numbers that the user inputs..
The problem is that my app is not doing any calculations now after updated my code to append . the decimal value to value whenever the user press the dot button. Which can be found Append or Add the decimal point functionality in calculator.
I have seen that the proper way to keep track of the inputs from the user and do the calculation is using the NSNumber but as I'm really new to Objective-c I have been struggling understanding the use and implementing it.
So, hopefully someone could walk me through to find the proper solution.
This is the header...
int Method;
float SelectNumber;
float RunningTotal;
bool DecimalActived;
#interface ViewController : UIViewController{
IBOutlet UILabel *Screen;
}
-(IBAction)Number9:(UIButton *)sender;
-(IBAction)Dot:(UIButton *)sender;
#end
This is the the implementation file..
-(IBAction)Number9:(UIButton *)sender{
[self appendDigit:#"9"];
}
- (IBAction)Dot:(UIButton *)sender {
NSString *currentText = Screen.text;
if ([currentText rangeOfString:#"." options:NSBackwardsSearch].length == 0) {
[self appendDigit:#"."];
}
}
- (void)appendDigit:(NSString *)digit {
// handle two special cases: append to only zero means just replace
// but append decimal point to zero is a regular append
if ([self->Screen.text isEqualToString:#"0"] && ![digit isEqual:#"."]) {
self->Screen.text = digit;
} else {
self->Screen.text = [Screen.text stringByAppendingString:digit];
}
}
- (IBAction)Percent:(UIButton *)sender {
[self MySwitch];
Method = 5;
SelectNumber = 0;
DecimalActived = FALSE;
Screen.text = [NSString stringWithFormat:#"%.2g", RunningTotal];
}
- (IBAction)PositiveOrNegative:(UIButton *)sender {
[self MySwitch];
Method = 6;
SelectNumber = 0;
DecimalActived = FALSE;
Screen.text = [NSString stringWithFormat:#"%g", RunningTotal];
}
-(IBAction)Equals:(UIButton *)sender{
[self MySwitch];
Method = 0;
SelectNumber = 0;
DecimalActived = FALSE;
Screen.text = [NSString stringWithFormat:#"%g", RunningTotal];
}
-(IBAction)AllClear:(UIButton *)sender{
Method = 0;
RunningTotal = 0;
SelectNumber = 0;
Screen.text = [NSString stringWithFormat:#"0"];
}
- (double) MySwitch {
NSNumberFormatter SelectNumber = [[NSNumberFormatter alloc] init];
[SelectNumber setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber RunningTotal = [SelectNumber numberFromString:self->Screen.text];
if (RunningTotal == 0) {
RunningTotal = SelectNumber;
} else{
switch (Method) {
case 1:
RunningTotal = RunningTotal * SelectNumber;
break;
case 2:
RunningTotal = RunningTotal / SelectNumber;
break;
case 3:
RunningTotal = RunningTotal - SelectNumber;
break;
case 4:
RunningTotal = RunningTotal + SelectNumber;
break;
case 5:
RunningTotal = RunningTotal / 100;
break;
case 6:
if(RunningTotal > 0){
RunningTotal = - RunningTotal;
} else{
RunningTotal = + RunningTotal;
}
break;
default:
break;
}
}
return RunningTotal;
}
If you guys have any question or need more information regarding my program please feel free to ask and I will provide as much information as possible or answer any questions that you guys may have.. :)
The header should look more like this:
// this uses more conventional (lowercase) property names
// and removes a couple that looked extraneous
#interface ViewController : UIViewController
#property(strong,nonatomic) IBOutlet UILabel *screen;
#property(assign,nonatomic) NSInteger method;
#property(strong,nonatomic) NSNumber *runningTotal;
#end
As the user presses digits, decimal, minus sign, append to the screen label as you have it. When the user presses an operation button, record an integer for the operation and record the current (NSNumber) value of the screen label. To do a computation...
- (void)doComputation {
float screenF = [[self screenValue] floatValue];
float runningF = [self.runningTotal floatValue];
float result;
switch (self.method) {
case 1:
result = runningF * screenF;
break;
case 2:
result = (screenF == 0.0)? 0.0 : runningF / screenF;
break;
case 3:
result = runningF - screenF;
break;
case 4:
result = runningF + screenF;
break;
default:
break;
}
self.screen.text = [NSString stringWithFormat:#"%0.8f", result];
self.runningTotal = [NSNumber numberWithFloat:result];
}
(screen value, as you have it...)
- (NSNumber *)screenValue {
NSNumberFormatter *f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
return [f numberFromString:self.screen.text];
}
How does this work?
NSNumberFormatter SelectNumber = [[NSNumberFormatter alloc] init];
[SelectNumber setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber RunningTotal = [SelectNumber numberFromString:self->Screen.text];
if (RunningTotal == 0) {
RunningTotal = SelectNumber;
} else{
switch (Method) {
case 1:
RunningTotal = RunningTotal * SelectNumber;
break;
This code shouldn't even work. Either SelectNumber is a float or it's a NSNumberFormatter*
I have a string, for example "Soccer". Now I want to move every "e" by lets say 2 indexes(right word?), so my string looks like this = "erSocc". This has to work with whitespace and negative/- indexes.
I came a cross with this, not perfect working, solution:
NSString* text = #"Soccer";
NSString* sign = #"c";
int index = 1;
NSMutableArray* arrayText = [[NSMutableArray alloc]init];
NSMutableArray* arraySignNewPosition = [[NSMutableArray alloc]init];
NSMutableArray* arrayOldSignPosition = [[NSMutableArray alloc]init];
for(int i=0;i<(text.length);i++)
{
[arrayText addObject:[text substringWithRange:NSMakeRange(i, 1)]];
if ([[arrayText objectAtIndex:i]isEqualToString:sign])
{
[arrayOldSignPosition addObject:[NSNumber numberWithInt:i]];
if ((i+index)>(text.length-1))
{
int indexDifference = (i+index)-(text.length);
[arraySignNewPosition addObject:[NSNumber numberWithInt:indexDifference]];
}
else
{
[arraySignNewPosition addObject:[NSNumber numberWithInt:(i+index)]];
}
}
}
for (NSNumber* number in arraySignNewPosition)
{
[arrayText insertObject:sign atIndex:number.integerValue];
if(number.integerValue-index>0)
{
[arrayText removeObjectAtIndex:(number.integerValue-index)];
}
else
{
[arrayText removeObjectAtIndex:((arrayText.count-1)+(number.integerValue-index))];
}
}
I know the code is not working perfectly, but I would like to know if this is the right way or if there are some Cocoa functions I could use to accomplish my goal. Thanks for your time.
You're really just getting substrings and moving them around, so you could do something like this:
- (NSString *)shiftRight:(NSUInteger)places
{
NSAssert(places > 0, #"places must be greater than 0");
NSAssert(places < [self length], #"places must be less than the length of the string");
places = [self length] - places;
NSString *start = [self substringFromIndex:places];
NSString *end = [self substringToIndex:places];
return [start stringByAppendingString:end];
}
Here's a complete code listing, with examples.
Can someone confirm for me this is the correct way to convert a NSString to an NSDecimalNumber? I have a label where when you click the button the price shows up, which is called totalPriceCalculated and then I also have all the strings where the calculations are made. Thanks in advance!
- (IBAction)calculateTotalPrice:(id)sender {
NSString *priceStringOne = [hiddenPriceOneTF text];
float priceFloatOne = [priceStringOne NSNumberFormatter];
NSString *priceStringTwo = [hiddenPriceTwoTF text];
float priceFloatTwo = [priceStringTwo floatValue];
NSString *priceStringThree = [hiddenPriceThreeTF text];
float priceFloatThree = [priceStringThree floatValue];
NSString *priceStringFour = [hiddenPriceFourTF text];
float priceFloatFour = [priceStringFour floatValue];
NSString *quanityStringOne = [quanityFirstTF text];
float quanityFloatOne = [quanityStringOne floatValue];
NSString *quanityStringTwo = [quanitySecondTF text];
float quanityFloatTwo = [quanityStringTwo floatValue];
NSString *quanityStringThree = [quanityThirdTF text];
float quanityFloatThree = [quanityStringThree floatValue];
NSString *quanityStringFour = [quanityFourthTF text];
float quanityFloatFour = [quanityStringFour floatValue];
float totalAmount = priceFloatOne * quanityFloatOne + priceFloatTwo * quanityFloatTwo + priceFloatThree * quanityFloatThree + priceFloatFour * quanityFloatFour ;
NSString *result = [NSString stringWithFormat:#" $ %0.2f", totalAmount];
[totalPriceCalculated setText:result];
NSString *totalPrice = totalPriceCalculated.text;
NSDecimalNumber *totalPriceNumber = (NSDecimalNumber *)totalPrice;
}
NSString *priceStringOne = [hiddenPriceOneTF text];
float priceFloatOne = [priceStringOne NSNumberFormatter];
UPDATED*
PayPalPayment *payment = [[PayPalPayment alloc] init];
payment.amount = [NSDecimalNumber decimalNumberWithString:totalPriceNumber];
payment.currencyCode = #"USD";
payment.shortDescription = #"Hipster t-shirt";
Another option is to create the decimal number from the float:
NSDecimalNumber *totalPriceNumber = [NSDecimalNumber decimalNumberWithDecimal:[#(totalAmount) decimalValue]];
According to the Apple docs, the prefered way is to use +decimalNumberWithString:; hope that helps.
Try:
totalPriceNumber = [[NSDecimalNumber alloc] initWithFloat:totalAmount];
I am trying to format long numbers in form of "k" for my axis labels. For example; if I have 10000, I would like it to be displayed as 10k.
I have already tried to follow this answer. But I could not manage to get formatted numbers. What I need to do additionally? Please guide me. Thanks.
EDIT:
HumanReadableFormatter.h
#interface HumanReadableFormatter : NSNumberFormatter
#end
HumanReadableFormatter.m
I have modified code from the link above to meet my requirements.
#import "HumanReadableFormatter.h"
#implementation HumanReadableFormatter
static const char sUnits[] = { '\0', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
static int sMaxUnits = sizeof sUnits - 1;
-(NSString *) stringForObjectValue:(id)obj
{
int multiplier = 1000;
int exponent = 0;
double bytes = [(NSNumber *)obj doubleValue];
while ((bytes >= multiplier) && (exponent < sMaxUnits)) {
bytes /= multiplier;
exponent++;
}
return [NSString stringWithFormat:#"%# %c", [super stringFromNumber: [NSNumber numberWithDouble: bytes]], sUnits[exponent]];
}
#end
Graph Code:
if(!rightY)
rightY = [[CPTXYAxis alloc]init];
rightY.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
rightY.orthogonalCoordinateDecimal = CPTDecimalFromFloat(totIntervalShown);
rightY.axisConstraints = [CPTConstraints constraintWithUpperOffset:-40];
rightY.coordinate = CPTCoordinateY;
rightY.majorTickLength = 0;
rightY.minorTickLength = 0;
rightY.tickDirection = CPTSignNone;
rightY.plotSpace = barPlotSpace;
NSNumberFormatter *numFormatter;
if(lowerLock < 1000) //if value is < 1000, normally format it
{
numFormatter = [[NSNumberFormatter alloc] init];
[numFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
numFormatter.maximumFractionDigits = 2;
numFormatter.minimumFractionDigits = 2;
}
else //for > 1000, format in human readable form
{
numFormatter = [[HumanReadableFormatter alloc] init];
//what i need to do here more?
}
rightY.labelFormatter = numFormatter;
//formatted as shown on right side on graph
Nested Loop:
I am posting solution, in case anyone needs it in future. Thanks to #Eric for helping me out.
HumanReadableFormatter.h
#interface HumanReadableFormatter : NSNumberFormatter
{
NSNumberFormatter *numberFormatter;
}
#end
HumanReadableFormatter.m
#implementation HumanReadableFormatter
static const char sUnits[] = { '\0', 'K', 'M', 'G', 'T', 'P', 'E', 'Z', 'Y' };
static int sMaxUnits = sizeof sUnits - 1;
-(id)init
{
if(self = [super init])
{
numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
numberFormatter.maximumFractionDigits = 1;
numberFormatter.minimumFractionDigits = 1;
}
return self;
}
-(NSString *) stringForObjectValue:(id)obj
{
int multiplier = 1000;
int exponent = 0;
double bytes = [(NSNumber *)obj doubleValue];
while ((bytes >= multiplier) && (exponent < sMaxUnits)) {
bytes /= multiplier;
exponent++;
}
NSString *convertedStr = [NSString stringWithFormat:#"%# %c", [numberFormatter stringFromNumber: [NSNumber numberWithDouble: bytes]], sUnits[exponent]];
return convertedStr;
}
#end
To use in graph, you need 2 lines of code:
HumanReadableFormatter *formatter = [[HumanReadableFormatter alloc] init];
YAxis.labelFormatter = formatter;
Since the labelFormatter uses an NSFormatter, your custom formatter should override -stringForObjectValue:, not -stringFromNumber: which is specific to NSNumberFormatter. Cast the argument to an NSNumber and you can use the same code for the method body.
I am trying to dectect if an NSString it's a float number, for exemple : #"-73.041382"
But when I try with this method I obtain a wrong result:
-(bool) isNumeric:(NSString*) checkText{
NSNumberFormatter* numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
NSNumber* number = [numberFormatter numberFromString:checkText];
if (number != nil) {
return true;
}
return false;
}
Someone have an idea!?
Thanks
I have found the answer :
-(bool) isNumeric:(NSString*) checkText{
NSNumberFormatter* numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
//Set the locale to US
[numberFormatter setLocale:[[[NSLocale alloc] initWithLocaleIdentifier:#"en_US"] autorelease]];
//Set the number style to Scientific
[numberFormatter setNumberStyle:NSNumberFormatterScientificStyle];
NSNumber* number = [numberFormatter numberFromString:checkText];
if (number != nil) {
return true;
}
return false;
}
Thanks!
-(bool) isNumeric:(NSString*) checkText{
return [[NSScanner scannerWithString:checkText] scanFloat:NULL];
}
i'm currently not on mac so i can't check it, hope it helps