Get warning when convert double to NSDecimalNumber - ios

I'm trying to convert a double to an NSDeciamlNumber. Here is my code:
- (NSDecimalNumber *)myMethod {
double amount = 42;
...
return [NSDecimalNumber numberWithDouble:amount]; // Get warning here
}
But I get the following warning:
Incompatible pointer types returning 'NSNumber *' from a function with result type 'NSDecimalNumber *'
What am I doing wrong, and how can I fix it?

numberWithDouble: method of NSDecimalNumber returns NSNumber.
In your method you want to return decimal so its OK if you allocate a new NSDecimalNumber with the decimal value (amount in your example).
May use the following way to get rid of the error:
-(NSDecimalNumber *)myMethod
{ double amount = 42; ...
return [[NSDecimalNumber alloc] initWithDouble: amount];
}

According to documentation [NSDecimalNumber numberWithDouble:_] returns a NSNumber so you should change the method declaration
- (NSNumber *)myMethod {
double amount = 42;
...
return [NSDecimalNumber numberWithDouble:amount]; // Get warning here
}

Try this. It may work out
- (NSNumber *)myMethod {
double amount = 42;
[NSNumber numberWithDouble:amount]
return [NSDecimalNumber numberWithDouble:amount];
}

numberWithDouble: method returns an NSNumber object but you suppose to return NSDecimalNumber.
Change it to
- (NSDecimalNumber *)myMethod {
double amount = 42;
return [[NSDecimalNumber alloc]initWithDouble:amount];
}

Try below code-
- (NSDecimalNumber *)myMethod {
double amount = 42;
...
return [[NSDecimalNumber alloc] initWithDouble: amount];
}

Related

Invalid operands to binary expression ('NSMutableArray' and 'double')

I want to store double value into Array and later combine to compute some results but I have encounter some error. Is there another way to do it?
NSMutableArray *storeImpedance;
NSMutableArray *storeLength;
double designFrequency = 1e9;
double simulateFrequency = 1.5e9;
double pi = 3.14159265359;
double omega = 2*pi*simulateFrequency;
double Z0=50;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
storeImpedance = [[NSMutableArray alloc]initWithCapacity:25];
storeLength = [[NSMutableArray alloc]initWithCapacity:25];
}
- (IBAction)addButton:(UIButton *)sender {
storeCount++;
[storeImpedance addObject:[NSNumber numberWithDouble:[impedanceTextField.text doubleValue]]];
[storeLength addObject:[NSNumber numberWithDouble:[lengthTextField.text doubleValue]]];
}
if (imageIndex==1)
{
thetarad=storeImpedance*pi/180*simulateFrequency/designFrequency;
A=cos(thetarad);
B=I* storeImpedance*sin(thetarad);
C=I*sin(thetarad)/storeImpedance;
D=cos(thetarad);
}
At this line:
hetarad=storeImpedance*pi/180*simulateFrequency/designFrequency;
You are using storeImpedance which is of type NSMutableArray and the expected type in this expressions is double.
Extract the required double value from the array and use it to fix the problem:
NSNumber *number = (NSNumber *)[storeImpedance firstObject]; // Or use objectAtIndex: for a specific value in the array if it is not the first one
double value = [number doubleValue];
hetarad=value*pi/180*simulateFrequency/designFrequency;
If you want to calculate hetarad for each value in the array:
for (id element in storeImpedance) {
NSNumber *number = (NSNumber *)element
double value = [number doubleValue];
hetarad=value*pi/180*simulateFrequency/designFrequency;
// You should do something with hetarad here (either store it or use in other required logic otherwise it will be overwritten by the next iteration
}

Remove negative symbol (-) from NSDecimalNumber gives me an error

I have an array with NSDecimalNumbers inside. I will do a check to see if that number is a negative number. If it is, I want to remove the negative sign (-). Here is my code:
NSString *amount = [myArray objectAtInde:2]; // Is a NSDecimalNumber with value of: -397.67
if ([amount doubleValue] < 0) {
amount = [amount stringByReplacingOccurrencesOfString:#"-" withString:#"- $"];
}
When I do that, I get the following error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSDecimalNumber stringByReplacingOccurrencesOfString:withString:]: unrecognized selector sent to instance 0x7fcaf94eff80'
Add below method in your source file
// multiplies number with -1 if it is less than zero else returns the same
- (NSDecimalNumber *)abs:(NSDecimalNumber *)num
{
if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending)
{
// Number is negative. Multiply by -1
NSDecimalNumber * negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1
exponent:0
isNegative:YES];
return [num decimalNumberByMultiplyingBy:negativeOne];
}
else
{
return num;
}
}
And convert instance of NSDecimalNumbers to abs value without doing any type conversion as-
NSDecimalNumbers *number = [myArray objectAtInde:2];
number = [number abs:number];
the number returned will contain abs value in NSDecimalNumbers format.
Try this,
NSDecimalNumber *amountNumber = [myArray objectAtIndex:2]; // Is a NSDecimalNumber with value of: -397.67
NSString *stringWithDollarSymbol = [self addDollarSymoblForNumber:amountNumber];
You can assign the stringWithDollarSymbol to label
- (NSString *)addDollarSymoblForNumber:(NSDecimalNumber *)decimalNum
{
NSString *modifiedString = #"";
if (decimalNum) {
NSString *numberInStringForm = [decimalNum stringValue];
if ([decimalNum doubleValue] < 0) { //adds dollor symbol for negative numbers
modifiedString = [numberInStringForm stringByReplacingOccurrencesOfString:#"-" withString:#"- $"];
}
else //adds dollor symbol for positive numbers
{
modifiedString = [NSString stringWithFormat:#"$ %#",modifiedString];
}
}
return modifiedString;
}
EDIT
More Better Approach using NSNumberFormatter:
- (NSString *)formatNumberBasedOnCurrentLocale:(NSDecimalNumber *)number
{
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setLocale:[NSLocale currentLocale]];
[formatter setNumberStyle:NSNumberFormatterCurrencyStyle];
NSString *result = [formatter stringFromNumber:number];
if (result.length >0) {
return result;
}
return nil;
}
Please add line,
if ([amount doubleValue] < 0) {
amount=[NSString stringWithFormat:#"%#",[myArray objectAtIndex:2]];//add line
amount = [amount stringByReplacingOccurrencesOfString:#"-" withString:#""];
}
it may be work for you,
I just used your code & it's working fine at my end.
Tried below thing,
NSString *amount = #"-397.67";//[myArray objectAtInde:2]; // Is a NSDecimalNumber with value of: -397.67
if ([amount doubleValue] < 0) {
amount = [amount stringByReplacingOccurrencesOfString:#"-" withString:#""];
}
Try it at your end.
If nothing will work then multiply your negative float value with -1 & you will get positive number. If that is your requirement.
Your [myArray objectAtInde:2] is a NSDecimalNumber rather than NSString, try this:
NSDecimalNumber *amountNumber = [myArray objectAtInde:2];
NSString *amount = [NSString stringWithFormat:#"%#", amountNumber];
Maybe you should try this one:
NSString *amount = #(ABS([myArray[2] doubleValue])).stringValue ; // Is a NSDecimalNumber with value of: -397.67
If your intention is to rescue from the negative then just simply convert the value into an absolute value.
NSString *amount = [myArray objectAtIndex:2]; // Is a NSDecimalNumber with value of: -397.67
NSLog(#"The value is : %#",[NSString stringWithFormat:#"%.2f", fabs([amount doubleValue])]);
The value is: 397.67

How do I get absolute value of NSCFNumber?

I have a value coming from an API server. The server stores it as BigDecimal on Postgres. On the iOS side, the value is of type __NSCFNumber. How do I get the absolute value for NSCFNumber?
My primary purpose is to further convert this number to a currency.
__NSCFNumber is an internal class that implements the NSNumber interface.
If you want a double:
NSNumber *myNumber = objectFromPostgres;
double value = fabs(myNumber.doubleValue);
If you want a long:
NSNumber *myNumber = objectFromPostgres;
long value = labs(myNumber.longValue);
If you want an int:
NSNumber *myNumber = objectFromPostgres;
int value = abs(myNumber.intValue);
You have a choice on the precision, but assuming a double value, you can use this:
NSNumber *number = [NSNumber numberWithDouble:-3.14159]; // isa Class __NSCFNumber 0x0000000101357a20
double absoluteValue = fabsl([number doubleValue]);
NSLog(#"absolute value = %f", absoluteValue);
Outputs:
absolute value = 3.141590
I asked an incomplete and vague question and I'm sorry. For my sins, I'm posting my solution and maybe it can help someone.
NSDecimalNumberHandler *roundUp = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundUp
scale:2
raiseOnExactness:NO
raiseOnOverflow:NO
raiseOnUnderflow:NO
raiseOnDivideByZero:YES];
NSDecimalNumber *totalAmount = [NSDecimalNumber decimalNumberWithDecimal:[user[#"total"] decimalValue]];
totalAmount = [[self abs:totalAmount] decimalNumberByRoundingAccordingToBehavior:roundUp];
The helper method that I got from this SO question.
- (NSDecimalNumber *)abs:(NSDecimalNumber *)num {
if ([num compare:[NSDecimalNumber zero]] == NSOrderedAscending) {
// Number is negative. Multiply by -1
NSDecimalNumber * negativeOne = [NSDecimalNumber decimalNumberWithMantissa:1
exponent:0
isNegative:YES];
return [num decimalNumberByMultiplyingBy:negativeOne];
} else {
return num;
}
}

How to return an NSNumber converted to NSInteger

With NSNumber being a class, I am trying to convert it to an NSInteger to do some computations. In NSLog, it shows that I am converting and doing the multiplication correct. However, when I got to return doubler as a regular NSInteger, I get "Implicit conversion of 'NSInteger' (aka 'long') to 'NSNumber* ' is disallowed with ARC". Where am I going wrong and what do I do to make this correct?
- (NSNumber *) numberThatIsTwiceAsBigAsNumber:(NSNumber *)number {
NSInteger doubler = [number integerValue] * 2;
NSLog(#"%ld", (long)doubler);
return doubler;
}
EDIT: For those curious, this is how I solved it:
NSInteger unboxing = [number integerValue] * 2;
NSNumber *boxing = [NSNumber numberWithInteger:unboxing];
return boxing;
You need to return the number as NSNumber, not NSInteger. So, convert the NSInteger to NSNumber before returning.
return #(doubler);
Change your return type to
- (NSInteger)
If you intend to continue to use it as such, or explicitly cast it.

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];

Resources