NSDecimalNumber, addition, and just not sure - ios

I'm not sure what to do next. They're just dollar amounts from a text field. I'm trying to add them together.
NSString *checkAmount = [checkAmountInput.text substringFromIndex:1];
NSDecimalNumber *checkAmountValue = (NSDecimalNumber*)[NSString stringWithFormat:#"%#",checkAmount];
NSLog(#"%#", checkAmountValue);
NSString *bankBalance = [bankBalanceInput.text substringFromIndex:1];
NSDecimalNumber *bankBalanceValue = (NSDecimalNumber*)[NSString stringWithFormat:#"%#",bankBalance];
NSLog(#"%#", bankBalanceValue);
NSDecimalNumber *totalAmount =
NSLog(#"%#",totalAmount);
When I try using decimalNumberByAdding I get:
'-[__NSCFString decimalNumberByAdding:]: unrecognized selector sent to instance 0x8a39a10'
Maybe I'm going about this all wrong... but I'm just starting out again.

Your checkAmountValue and bankBalanceValue aren't actually NSDecimalNumber instances. Casting an NSString to an NSDecimalNumber will silence a compiler warning, but the objects are still just strings.
You can use decimalNumberWithString: to create an actual NSDecimalNumber instance from a string:
NSString *bankBalance = [bankBalanceInput.text substringFromIndex:1];
NSDecimalNumber *bankBalanceValue = [NSDecimalNumber decimalNumberWithString:bankBalance];

There's some mixed up code there. Effectively, what you want to do is grab the text from two NSTextFields, and convert them to NSDecimalNumbers and add them. You can certainly do that. Be aware that NSTextField, can also 'parse' the string value directly and return you a numeric type (int, double, float) directly:
double d = [textField doubleValue];
If you still wanted to use NSDecimalNumber, and parse it from an NSString:
NSString *s = [textField stringValue];
To convert the string to an NSDecimalNumber:
NSDecimalNumber *n1 = [NSDecimalNumber decimalNumberWithString:s]
NSDecimalNumber *n2 = // repeat as above for the second string
To add them together:
NSDecimalNumber *n3 = [n1 decimalNumberByAdding:n2];
Note that, decimalNumberWithString is a class factory method which creates an instance of NSDecimalNumber by parsing a string. In your case you were simply casting to this which really doesn't create the type that you need.

Related

What is the difference between #"1.5" and #(1.5) while setting the value in NSDictionary?

In iPhone project,
It was while I was while setting Value in dictionary,
NSMutableDictionary*dictionary=[[NSMutableDictionary alloc] init];
[dictionary setValue:#(2.8) forKey:#"Why"];
AND,
NSMutableDictionary*dictionary=[[NSMutableDictionary alloc] init];
[dictionary setValue:#"2.8" forKey:#"Why"];
My question is Why not #"2.5" and #(2.5) ?
You have two questions, it would be better to have a single question.
But as to the difference,#"2.5" is an NSString where #(2.5) is an NSNumber. There is a big difference between textual and numeric data.
As for why you need an NSNumber and not NSString is obvious: the kerning is a numeric value.
using the #() syntax you can box arbitrary C expressions. This makes it trivial to turn basic arithmetic calculations into NSNumber objects see below:
double x = 24.0;
NSNumber *result = #(x * .15);
NSLog(#"%.2f", [result doubleValue]);
You can also refer NSNumber object as #"" string but cant make calculations like above example. In your case both are acceptable but here calculation makes difference.
When you use
#"2.5" it's behave like a string
NSMutableDictionary*dictionary=[[NSMutableDictionary alloc] init];
[dictionary setValue:#"2.8" forKey:#"Why"];;
NSString *a = [dictionary ValueforKey:#"Why"];
but when you use #(2.8) then it's behave like a NSNumber
NSMutableDictionary*dictionary=[[NSMutableDictionary alloc] init];
[dictionary setValue:#(2.8) forKey:#"Why"];;
NSNumber *a = [dictionary ValueforKey:#"Why"];
#(2.8) is a type of NSNumber.
#"2.8" is a type of NSString.
Both the type and value were different between there two.

Conversion issue from NSNumber to NSString

I'm parsing data from a JSON webservice and adding it to the database so when I insert an int, I have to convert it to NSNumber in this way it's working fine: 24521478
NSString *telephone = [NSString stringWithFormat:#"%#",[user objectForKey:#"telephone"]];
int telephoneInt = [telephone intValue];
NSNumber *telephoneNumber = [NSNumber numberWithInt:telephoneInt];
patient.telephone = telephoneNumber;
but when I want to display it and convert the NSNumber to NSString I'm getting wrong numbers: -30197
NSString *telephoneString = [NSString stringWithFormat:#"%d", [user.telephone intValue], nil];
labelTelephone.text =telephoneString ;
Can someone explain this?
NSNumber comes with dedicated methods for each data type.If you want to convert NSNumber to NSString use:
NSString *telephoneString = [user.telephone stringValue];
The issue may coming because of the data type you used for the variable patient.telephone
If you have control over the web service, then you should return the telephone number as string in the JSON
Reasons
if the telephone number begin with zero then the NSNumber will remove that zero as it has no value (ex: 00123456789 will be 123456789 which will wrong data)
You will not be able to display the telephone number is a user friendly way by adding "+" and "-" (ex: +123-456-789)
You really should make the json return the number as string if you have a control over that

How to divide NSDecimalNumber by integer?

I don't think a comprehensive, basic answer to this exists here yet, and googling didn't help.
Task: Given an NSDecimalNumber divide this by an int and return another NSDecimalNumber.
Clarification: amount_text below must be converted to a NSDecimalNumber because it is a currency. The result must be a NSDecimalNumber, but I don't care what format the divisor is.
What I have so far:
// Inputs
NSString *amount_text = #"15.3";
int n = 10;
NSDecimalNumber *total = [NSDecimalNumber decimalNumberWithString:amount_text];
// Take int, convert to string. Take string, convert to NSDecimalNumber.
NSString *int_string = [NSString stringWithFormat:#"%d", n];
NSDecimalNumber *divisor = [NSDecimalNumber decimalNumberWithString:int_string];
NSDecimalNumber *contribution = [total decimalNumberByDividingBy:divisor];
Surely, this can be done in a more straightforward way?
Is there any reason why you're using NSDecimalNumber? This can be done way easier like this:
// Inputs
NSString *amount_text = #"15.3";
int n = 10;
float amount = [amount_text floatValue];
float result = amount / n;
If you really want to do it with NSDecimalNumber:
// Inputs
NSString *amount_text = #"15.3";
int n = 10;
NSDecimalNumber *total = [NSDecimalNumber decimalNumberWithString:amount_text];
NSDecimalNumber *divisor = [NSDecimalNumber decimalNumberWithMantissa:n exponent:0 isNegative:NO];
NSDecimalNumber *contribution = [total decimalNumberByDividingBy:divisor];
You can always use initialisers when creating NSDecimalNumber. Since it is a subclass of NSNumber, NSDecimalNumber overrides initialisers.
So you can do
NSDecimalNumber *decimalNumber = [[NSDecimalNumber alloc] initWithInt:10];
however, you should be careful if your are doing high precision calculations as there are some problems using these initialisers. You can read about it here in more detail.
Alternatively (potentially losing some precision):
double amount = 15.3;
double n = 10.0;
double contribution = amount / n;
// conversion to decimal
NSString *string = [NSString stringWithFormat:#"%f", n];
NSDecimalNumber *contribution_dec = [NSDecimalNumber decimalNumberWithString:string];
better yet (if n=10):
[dec decimalNumberByMultiplyingByPowerOf10:-1];
As per your code...
You are creating an NSDecimalNumber from string and then doing manipulations with it.
I never do that. Unless you need NSDecimalNumber unless you want a boxed Objective-C Object, Avoid it, use float and double.
If you want to do it much simpler you can do it as:
float quotient = [total floatValue]/n;
or,
float quotient = [contribution floatValue]/n;
EDIT: If you want with any specific reason to use boxed type then you can use as:
NSString *amount_text = #"15.3";
int n = 10;
NSDecimalNumber *total = [NSDecimalNumber decimalNumberWithString:amount_text];
NSDecimalNumber *divisor = [[NSDecimalNumber alloc] initWithInt:n];
NSDecimalNumber *contribution = [total decimalNumberByDividingBy:divisor];

Convert long NSString to NSNumber

I am unable to reliably convert longer NSString to NSNumber. Specifically, I am converting MPMediaEntityPropertyPersistentID as a string to a NSNumber Sometimes it works, usually it doesn't.
Conversion code:
NSString *keke = [jsonArray objectForKey:#"next"];
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
[f setNumberStyle:NSNumberFormatterDecimalStyle];
NSNumber *persistentIDasNumber = [f numberFromString:keke];
Here is an example of a successful string to number conversion:
String: 3813955856659208324
Number: 3813955856659208324
And here is an unsuccessful conversion:
String: 12790162104953153719
Number:1.279016210495315e+19
It's close but what is happening at the end? Is it too large?
Apparently the largest integer number that can be processed with NSNumberFormatter is long long, which is 9223372036854775807. Anything beyond that will lose precision and not come out as you put it in.
Instead use NSDecimalNumber, a concrete subclass of NSNumber. And it can even parse strings itself:
NSDecimalNumber *dn=[[NSDecimalNumber alloc]initWithString:#"12790162104953153719"];
NSLog(#"dn: %#",dn);
NSDecimalNumber can handle up to 38 digit long decimal numbers before it loses precision.
This is how you do it:
unsigned long long number = [[jsonArray objectForKey:#"next"] longLongValue];
NSNumber * numberValue = [NSNumber numberWithUnsignedLongLong:number];

Why aren't these NSString instance variables allocated?

first post here. I was reading through an Objective-C tutorial earlier, and I saw that they had made a couple of NSString instance variables like this:
#implementation MyViewController {
NSString *stringOne;
NSString *stringTwo;
NSString *stringThree;
NSString *stringFour;
NSString *stringFive;
}
And then simply used them in ViewDidLoad like this:
- (void)viewDidLoad
{
[super viewDidLoad];
stringOne = #"Hello.";
stringTwo = #"Goodbye.";
stringThree = #"Can't think of anything else to say.";
stringFour = #"Help...";
stringFive = #"Pheww, done.";
}
How have they done this without instantiating the string? Why does this work? Surely you'd have to do something like stringOne = [NSString stringFromString:#"Hello."]; to properly alloc and init the object before you could simply do stringOne= #"Hello.";.
Sorry if this a dumb question, but I find these little things throw me.
Thanks,
Mike
From the Apple String Programming Guide:
Creating Strings
The simplest way to create a string object in source code is to use the Objective-C #"..." construct:
NSString *temp = #"Contrafibularity";
Note that, when creating a string constant in this fashion, you should use UTF-8 characters. Such an object is created at compile time and exists throughout your program’s execution. The compiler makes such object constants unique on a per-module basis, and they’re never deallocated. You can also send messages directly to a string constant as you do any other string:
BOOL same = [#"comparison" isEqualToString:myString];
String constants like #"Hello" are already allocated and initialized for you by the compiler.
Just remember this basic thing:-
NSString *string = ...
This is a pointer to an object, "not an object"!
Therefore, the statement: NSString *string = #"Hello"; assigns the address of #"Hello" object to the pointer string.
#"Hello" is interpreted as a constant string by the compiler and the compiler itself allocates the memory for it.
Similarly, the statement
NSObject *myObject = somethingElse;
assigns the address of somethingElse to pointer myObject, and that somethingElse should already be allocated and initialised.
Therefore, the statement: NSObject *myObject = [[NSObject alloc] init]; allocates and initializes a NSObject object at a particular memory location and assigns its address to myObject.
Hence, myObject contains address of an object in memory, for ex: 0x4324234.
Just see that we are not writing "Hello" but #"Hello", this # symbol before the string literal tells the compiler that this is an object and it returns the address.
I hope this would answer your question and clear your doubts. :)
actually this can be said "syntactic sugar". there are some other type of NS object that can be creatable without allocation or formatting.
e.g:
NSNumber *intNumber1 = #42;
NSNumber *intNumber2 = [NSNumber numberWithInt:42];
NSNumber *doubleNumber1 = #3.1415926;
NSNumber *doubleNumber2 = [NSNumber numberWithDouble:3.1415926];
NSNumber *charNumber1 = #'A';
NSNumber *charNumber2 = [NSNumber numberWithChar:'A'];
NSNumber *boolNumber1 = #YES;
NSNumber *boolNumber2 = [NSNumber numberWithBool:YES];
NSNumber *unsignedIntNumber1 = #256u;
NSNumber *unsignedIntNumber2 = [NSNumber numberWithUnsignedInt:256u];
NSNumber *floatNumber1 = #2.718f;
NSNumber *floatNumber2 = [NSNumber numberWithFloat:2.718f];
// an array with string and number literals
NSArray *array1 = #[#"foo", #42, #"bar", #3.14];
// and the old way
NSArray *array2 = [NSArray arrayWithObjects:#"foo",
[NSNumber numberWithInt:42],
#"bar",
[NSNumber numberWithDouble:3.14],
nil];
// a dictionary literal
NSDictionary *dictionary1 = #{ #1: #"red", #2: #"green", #3: #"blue" };
// old style
NSDictionary *dictionary2 = [NSDictionary dictionaryWithObjectsAndKeys:#"red", #1,
#"green", #2,
#"blue", #3,
nil];
for more information, see "Something wonderful: new Objective-C literal syntax".

Resources