dsch
dsch

Reputation: 117

Objective-C - Wrong output on simple math

I am learning Objective-C and iOS development by making a simple tip calculator. However, the issue I am having is when I try to calculate the tip. This is simple math (tip percent / total bill) * 100. This is exactly what I am doing, but I am really confused as to why my output is wrong.

This is the method in my ViewController.m file that is giving me issues

- (IBAction)doCalculate:(id)sender {
    NSInteger totalBillAmount = self.inputTotalBill.text.intValue;
    NSLog(@"input total bill: %i", totalBillAmount);
    NSInteger tipPercent = self.inputTip.text.intValue;
    NSLog(@"input tip percent: %i", tipPercent);

    NSInteger tipAmount = (tipPercent / totalBillAmount) * 100;
    NSLog(@"tip amount: %i", tipAmount);
    NSInteger billAmount = totalBillAmount + tipAmount;
    NSLog(@"total bill: %i", billAmount);

    // Set labels accordingly
    self.labelTipAmount.text = [NSString stringWithFormat:@"%i", tipAmount];
    self.labelBillAmount.text = [NSString stringWithFormat:@"%i", billAmount];
}

And this is my output:

2016-02-28 01:39:36.283 conversion[1533:58347] input total bill: 100
2016-02-28 01:39:36.285 conversion[1533:58347] input tip percent: 15
2016-02-28 01:39:36.285 conversion[1533:58347] tip amount: 0
2016-02-28 01:39:36.285 conversion[1533:58347] total bill: 100

I am really confused so any help is appreciated, thanks!

Upvotes: 0

Views: 118

Answers (3)

Fennelouski
Fennelouski

Reputation: 2431

When you divide two NSIntegers, the result is one NSInteger. If that fraction is <1 and >0 then the output is 0. Using NSInteger might not be the best option here if you want it to be simple.

NSInteger tipAmount = (tipPercent * totalBillAmount) / 100;
NSLog(@"tip amount: %i", tipAmount); // tip amount: 0

If you used a float, it would be a whole lot cleaner:

float tipAmount = (tipPercent * totalBillAmount) / 100;
NSLog(@"tip amount: $%.02f", tipAmount); // tip amount: $15.00

However, using floats for currency can be very bad. So, it would be a more sage decision to use NSInteger to keep track of the smallest unit of currency instead. For the USD this is $0.001, or one tenth of a cent.

This means, when someone enters the bill total, let's say $100.00, you would record that value as 100000.

Then, to calculate 15%, you would multiply the bill by 15 and then divide by 100.

NSInteger tipAmount = (tipPercent * totalBillAmount) / 100;
NSLog(@"tip amount: %i", tipAmount); // tip amount: 15000

To show the user again, I would use a method like the following to convert from tenth cent units to a formatted string for dollars:

- (NSString *)tenthCentToDollarString:(NSInteger)tenthCents {
    if (tenthCents >= 0) {
        NSInteger roundedCents = (tenthCents + 5) / 10;

        if (roundedCents < 10) {
            return [NSString stringWithFormat:@"$0.0%zd", roundedCents];
        }

        if (roundedCents < 100) {
            return [NSString stringWithFormat:@"$0.%zd", roundedCents];
        }

        NSInteger cents = roundedCents % 100;
        NSInteger dollars = roundedCents / 100;

        if (cents < 10) {
            return [NSString stringWithFormat:@"$%zd.0%zd", dollars, cents];
        }

        return [NSString stringWithFormat:@"$%zd.%zd", dollars, cents];
    }

    // Dollar amount is negative
    NSInteger positiveTenthCents = ABS(tenthCents);
    NSString *dollarString = [self tenthCentToDollarString:positiveTenthCents];
    return [NSString stringWithFormat:@"-%@", dollarString];
}

Upvotes: 1

Jean-Baptiste Yun&#232;s
Jean-Baptiste Yun&#232;s

Reputation: 36391

Computer numbers does not behave like numbers you learned at school. Integers only use integer arithmetic, and then integer division (look on the web).

4/100 (as an integer division) gives 0 (remember Euclidian division?) If you want to make more natural computations, use floats or doubles (but they will surprise you even more later!).

Upvotes: 1

sschale
sschale

Reputation: 5188

A couple issues: You should be doing tipAmount = (tipPercent / 100) * totalBillAmount and cast to doubles because NSInts can't do fractions.

Upvotes: 0

Related Questions