Multiplication of 2 decimal number values Objective C - ios

I am doing multiplication of 2 values in Objective c which seems very simple yes but the result i get after multiplication is not correct the last digit after decimal point is changing the value. The code i used to do multiplication is below.
NSDecimalNumber* x = rpnStack.back(); rpnStack.pop_back();
NSDecimalNumber* y = rpnStack.back(); rpnStack.pop_back();
NSDecimalNumber* z = [y decimalNumberByMultiplyingBy:x]; // y * x;
The value of x = 20.16
The value of y = 51.3934970238095
The result of z is = 1036.0928999999995, which is should be 1036.0928999999996 as tested in many calculators. Can anyone give me some hint how can i fix this last number ?

NSDecimalNumber provides the correct answer. Try verifying the result by hand.
51.3934970238095
* 20.16
--------------------
3.083609821428570
5.13934970238095
0.0
+ 1027.869940476190
----------------------
1036.092899999999520

When you print NSDecimalNumber in console it rounds according to rounding behavior provided, usually default. Please refer to NSNumberFormatter and NSNumberFormatterRoundingMode when printing NSDecimalNumbers.
See:
https://developer.apple.com/reference/foundation/nsdecimalnumber?language=objc
https://developer.apple.com/reference/foundation/nsdecimalnumberhandler
https://developer.apple.com/reference/foundation/nsnumberformatter

I get the correct value by using NSNumber instead of NSDecimalNumber
NSNumber *x = #(20.16);
NSNumber *y = #(51.3934970238095);
NSNumber *z = #(x.doubleValue * y.doubleValue); //1036.0928999999996

Related

A working function but having trouble with a particular float value

This function takes a float then spits out the two integers for the decimal value. At least that was the intention
let flr (x:float) = float(int(x))
let f x =
let r y = let x = x * y in x = flr(x)
let rec f y =
if r(y)
then x*y,y
else f(y+1.0)
f 1.0
f 0.2;;
val it: float * float = (1.0, 5.0)
f 3.14;;
val it: float * float = (157.0, 50.0)
Here is an example where the integers, er will be integers eventually rather, have not been "simplified"
f 0.14;;
val it: float * float = (35.0, 250.0)
Checking the fractional part to be less than .01, as opposed to equaling exactly zero, got around this issue but I don't really like that solution. So I set it back to what you see in the code above. I am using the function below for some of the values that do not simplify though:
let g (x,y) =
let rec f k =
if x/k = flr(x/k)
then g(k)
else f(k-1.0)
and g k =
if y/k = flr(y/k)
then x/k,y/k
else f(k-1.0)
if x < y then f x else f y
Anyway, the main issue is this value:
3.142857143
Homeboy just keeps grinding without stack errors and I'm not sure what I've ran into here. Any clarity would be awesome! Thanks y'all.
Your algorithm is trying to find a rational number to represent a decimal number (represented as a floating point number).
For any input x, you are looking for a number represented as p/q such that x=p/q and you do this by incrementing q, starting from 1 and checking if you can find an integer p to make this work.
This works fine for numbers that have a nice rational representation like 0.2, but it does not work great for numbers like 3.142857 that do not have a simpler rational representation. For 3.142857, you will just keep iterating until you reach 3142857/1000000 (which is technically correct, but not very helpful).
As mentioned in the comments, there are issues caused by the fact that floating-point numbers cannot be precisely compared, but also, iterating like this for 3.142857143 might just take too long.
You can look up better algorithms for finding a rational number for a given decimal. You could also see if you can accept some margin of error. If you do not need a completely precise solution, you could for example change your r test function to something like:
let r y =
let x = x * y
x < flr(x) + 0.0001 && x > flr(x) + 0.0001
This will not give you exactly the same number, but it will likely find a solution that is good enough.

Dynamic values in percentage format in Objective C

I want to know making Objective C variable values in percentage format. I am getting 6 values dynamically. Sometimes values might increase more than 100. For ex: Avalue=143, Bvalue=450, Cvalue=76, Dvalue=98, Evalue=123, Fvalue=56
how can i format each value under percentage format?
(Avalue * 100)/100.f
(Bvalue * 100)/100.f
(Cvalue * 100)/100.f
(Dvalue * 100)/100.f
(Evalue * 100)/100.f
(Fvalue * 100)/100.f
Is this proper way of doing it?
Well, percentage numbers are in essence fractions. In mathematics, a percentage is a number or ratio expressed as a fraction of 100.
if you want to compare numbers like in your case, compare each numbers to the sum oaf all value, then set the sum as 100%.
float sumAllValues = (Avalue + Bvalue + ...);
float aValuePercent = (Avalue / sumAllValues) * 100.f
you can format that percentage number with NSNumberFormatter
NSString *result1 = [NSNumberFormatter localizedStringFromNumber:[NSNumber numberWithFloat:aValuePercent];
numberStyle:NSNumberFormatterPercentStyle];
btw: why the variables begin with a Uppercase?
-Edit-
When you divide integers, keep in mind that integers divided by integer results integer.
I wrote a short example for the console.
NSInteger a = 5;
NSInteger b = 6;
NSInteger c = a * 100 / b;
NSInteger d = a / b * 100;
// example with conversion al values to float
float e = [[NSNumber numberWithInteger:a] floatValue] / [[NSNumber numberWithInteger:b] floatValue] * 100;
NSLog(#"resulting int c: %lu", c);
NSLog(#"resulting int d: %lu", d);
NSLog(#"resulting float e: %f", e);
2017-02-14 19:36:54.897 IntegerTest[2291:1238166] resulting int c: 83
2017-02-14 19:36:54.898 IntegerTest[2291:1238166] resulting int d: 0
2017-02-14 19:36:54.898 IntegerTest[2291:1238166] resulting float e: 83.333328
Program ended with exit code: 0
You see, when you multiply the first integer with 100 and the divide, you get 83.
The other way round (what is mathematically correct), first the division and after the multiply, you get 0, because 5/6 is less than 1 and the integer value is set to 0. Since multiplying 0 by any other value remains 0, the result is 0.
EDIT AGAIN -
the code from console is written with plain integers, but in essence they are the same as your values. First the multiplication, then the division.
NSInteger aPercentage = (Avalue * 100) / Bvalue;
or cast all values to floats. like so:
float aValueFloat = [[NSNumber numberWithInt:Avalue] floatValue];
EDIT AGAIN -
This was only for example reasons. Value is only the divisor because I do not know, to wash value you want to compare those values. In this example Avalue is compared to Bvalue, say Avalue is percent from Bvalue.
If you only want to print out Avlue = 143 in 143% then:
NSInteger aValue = 146;
NSString *aValuePercentString = [NSString stringWithFormat:#"%ld%%", aValue];
NSLog(#"%#", aValuePercentString);
Output: 2017-02-15 16:52:26.346 test[2132:1070601] 146%
Note1: This works with values as Integers. If the values are NSNumbers use %# instead of %ld.
Note2: Value is not an Integer anymore but a string.
Hope it helps!

how to save a float to nsnumber with just two decimals

I'm trying to save a float to an nsnumber but i just want to save it with two decimal places. I know I can do it by converting to an NSString first using this code
NSString* formattedNumber = [NSString stringWithFormat:#"%.02f", myFloat];
but seems clumsy. All I want to do is convert
float numb = 23.25454 into NSNumber 23.25
Use this
float numb = 23.25454;
NSNumber *num = #((int)(numb*100)/100.0);
Just round it using any of these functions
float rounded = round(val * 100) / 100;
float rounded_down = floorf(val * 100) / 100;
float nearest = floorf(val * 100 + 0.5) / 100;
float rounded_up = ceilf(val * 100) / 100;
If you're looking for an object oriented approach, try using NSDecimalNumber which is a subclass of NSNumber. Init the NSDecimalNumber with your float value and then call decimalNumberByRoundingAccordingToBehavior:. This gives you a few options of how the truncation or rounding occurs with NSDecimalNumberBehaviors, where you can set the scale (number of digits following the decimal) and an NSRoundingMode. Check the docs for more info.
It is impossible to do this with float, double, or either of those wrapped as an NSNumber. You need to understand how floating point works.
All these use binary numbers, you wish to represent a number with exactly two decimal places. A binary fraction is made up from a sum of 1/2, 1/4, 1/8, 1/16... while a decimal fraction is a sum of 1/10, 1/100, 1/1000... Not all values which can be represented as a sum of values in one of this series can be represented as a sum in the other. This is a similar issue to representing 1/3 in decimal, it is 3/10 + 3/100 + 3/1000 + .....
Try writing, for example, 0.17 = 17/100 = 1/10 + 7/100 as a sum of 1/2, 1/4 etc. Well it's 1/8 + 9/200 = 1/8 + 1/32 + 11/8000 (I'm just doing this on the fly, excuse any errors!) = you figure it out!
To address this there is the NSDecimalNumber class, which is a subclass of NSNumber and represents numbers in base-10. The class provides the basic operations to do base-10 arithmetic. You can't mix arithmetic easily between base-10 and base-2 numbers, you cannot even create an NSDecimalNumber directly from a float or double - you format the later as an NSString (i.e. convert them to a base-10 representation) - and extracting a double value with the doubleValue method is described as:
The approximate value of the receiver as a double.
Note the approximate.
So a long answer to get to a question: do you really want to store a float or double value to exactly two decimal places?
You can use the round, floor & ceil families to do it approximately, but be prepared for results that are "wrong". E.g. try:
float a = 371371.28127;
float b = roundf(a * 100.0) / 100.0;
NSLog(#"a: %f | b: %f", a, b);
HTH
NSDecimalNumber with NSDecimalNumberHandler is the best way to get accurate precisions if you want as Object. Below is the sample code.
-(NSDecimalNumber *)getRoundedNumberAfterPointDigitsCount:(int)digitsCount withDouble:(double)doubleValue{
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:#"%f",doubleValue]];
NSDecimalNumberHandler *decimalHandler = [[NSDecimalNumberHandler alloc] initWithRoundingMode:NSRoundPlain scale:digitsCount raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
decimalNumber = [decimalNumber decimalNumberByRoundingAccordingToBehavior:decimalHandler];
return decimalNumber;
}
There is more of Rounding option available with NSRoundingMode.
float numb = 23.25454;
float myFloat = roundf(100 * numb) / 100.0;
NSNumber *number = [NSNumber numberWithFloat:myFloat];

Formatting an integer value

Im obtaining an int value from UITextField [self.dbRef.text intValue];
I want to then format that value so I can add a decimal place that precceds the number ie. If [self.dbRef.text intValue]; returns 4 i need that value to be 0.04
So far I have tried various ways including
float Y = ([self.dbRef.text intValue]/100);
slice.value = Y;
NSLog(#"float Y value = %f",Y);
returns zero
NSString* formatedTotalApplianceString = [NSString stringWithFormat:#"0.%#", self.dbRef.text];
NSLog(#"formated string = %#",formatedTotalApplianceString);
int totalAppliances = [formatedTotalApplianceString intValue];
NSLog(#"Resulting int value = %d",[formatedTotalApplianceString intValue]);
slice.value = totalAppliances;
NSLog(#"total appliances int value = %d",totalAppliances);
returns zero
You're doing an integer division, so the 0 value is correct in that context as integers cannot represent fractions (unless you're doing fixed point arithmetics, but that's a different can of worms). You need to do a floating point division, for example:
float Y = ([self.dbRef.text floatValue]/100.0f);
Either the [self.dbRef.text floatValue] or the 100.0f will turn this into a float division, because if the other side would be an int it would automatically get casted to a float. But the "best" way is to have both values of the same type.
Change
float Y = [self.dbRef.text intValue]/100;
to
float Y = ((float)[self.dbRef.text intValue])/100;
in your first variant.
Dividing int by int returns you int result even if then you assign it to float. 4/100 = 0 in such case.
The problem with [self.dbRef.text intValue]/100 is that it's an integer division. It drops the fraction. One way to work around it is to divide by 100.0:
[self.dbRef.text intValue]/100.0
However, this is not the most efficient way of doing it if all you need is adding a zero in front of a fraction: you could avoid float altogether by padding your printed int to two positions with leading zeros:
// If text is 4, the code below prints 0.04
NSLog(#"0.%02d", [self.dbRef.text intValue]);
The first code returns zero because you are performing an integer division, which produces an integer result. You should cast the value to a float.
The second code also returns zero because you're asking for the intValue of a floating point value. So the decimal part will be discarded.
NSString has also a floatValue method, you should use it to get a floating value. Once divided by 100 you will still have a floating point value (in a division if the quotient or the dividend is a float and the other an integer, the integer gets promoted to float):
float Y = ([self.dbRef.text floatValue]/100);
slice.value = Y;

Division in iOS Xcode

Not terribly familiar with Xcode or Objective-C but trying to learn. Hopefully someone can help me out with a problem I'm having.
I have two fields, one called price and one called units and I'm trying divide the inputs of the cells by each other and then display the result with the correct currency of the 'nationality' of the device when a button is pressed.
So far I have of the action of the button I have;
- (IBAction)calculate:(id)sender {
int x = [price.text floatValue];
int y = [units.text floatValue];
int calc_result = x / y;
self.result.text = [NSString stringWithFormat:#"%.2f", calc_result];
}
which outputs a result into a label field WITHOUT the decimal remainder.
How can I get it to display the decimal remainder to 2 decimal places and put in front the currency found from the 'nationality' of the device.
Thanks in advance!
You are using an integer here:
int x = [price.text floatValue];
int y = [units.text floatValue];
int calc_result = x / y;
You should use a floating point number:
float x = [price.text floatValue];
float y = [units.text floatValue];
float calc_result = x / y;

Resources