Convert String to Double with Currency - ios

NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle: NSNumberFormatterCurrencyStyle];
double value = [[numberFormatter numberFromString: ProviderTripRate.text] doubleValue];
[User setDouble:value forKey:#"Trip_Rate"];
NSLog(#" %# %f " , ProviderTripRate.text , value );
If the data inside ProviderTripRate.text is 2.75 then value is 0 wrong
If the data inside ProviderTripRate.text is $2.75 then value is 2.75 correct
How do you reliably convert from the string to a double value
NOTE that the text string may or may NOT have the local currency symbol ($ as shown above)
but it should always convert
Thanks in advance

Try this:
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle: NSNumberFormatterCurrencyStyle];
NSNumber* number = [numberFormatter numberFromString:ProviderTripRate.text]
if (!number) {
[numberFormatter setNumberStyle: NSNumberFormatterDecimalStyle];
number = [numberFormatter numberFromString:ProviderTripRate.text];
}
double value = [number doubleValue];

Try this:
if ([providerTripRate.text hasPrefix:#"$"]) {
// use NSNumberFormatter to obtain the value
} else {
float theValue = [providerTripRate.text doubleValue];
}
etc.

extension String {
/// Creates a Double from the string
///
/// Tries various ways of extracting a number, currently handling the following formats
/// - 1000
/// - 1000.00
/// - 1,000.00
/// - $1,000.00
///
/// - Returns: Double value, or 0.0 if a non numerical String is passed
func asDouble() -> Double {
if let double = Double(self) {
return double
}
let formatter = NumberFormatter()
if let number = formatter.number(from: self) {
return number.doubleValue
}
formatter.numberStyle = .currency
if let number = formatter.number(from: self) {
return number.doubleValue
}
formatter.currencySymbol = ""
formatter.internationalCurrencySymbol = ""
if let number = formatter.number(from: self) {
return number.doubleValue
}
return 0
}
}

Related

How to format a float value in Objective-C

- (NSString *)_stringToFloat:(NSNumber *)number {
if (number && number > 0) {
return [NSString stringWithFormat:#"%.2f",[number floatValue]];
}
return #"0.0";
}
Using:
_lblAppointmentFee.text = [[NSString alloc]initWithFormat:#"%#",[self_stringToFloat:[_dicObject objectForKeyNotNull:#"rate"]]];
How can I can return "5.21" for a value of 5.21 and return "5" for a value of 5.00?
Use an NSNumberFormatter. Set the desired fraction digits.
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
nf.numberStyle = NSNumberFormatterDecimalStyle;
nf.minimumFractionDigits = 0;
nf.maximumFractionDigits = 2;
NSString *result = [nf stringFromNumber:#(5.12)];
This gives a result of "5.12" while:
result = [nf stringFromNumber:#(5.00)];
gives a result of "5".
This also has the added bonus of properly formatting the result based on the user's locale.

Convert NSSting to NSDecimalNumber based on locale

I want to convert a number which is input as NSString to NSDecimalNumber based on NSLocale.
for example
InputString => 110.50
Current Locale => en_FI
Expected output => 110.50
Actual output => 110
InputString => 110.50
Current Locale => en_US
Expected output => 110.50
Actual output => 110.50
InputString => 110,50
Current Locale => en_US
Expected output => 110.50
Actual output => 110
InputString => 110.50
Current Locale => en_US
Expected output => 110.50
Actual output => 110.50
I am using the following code to achieve this but its not working.
NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:self.amountTextField.text locale:[NSLocale currentLocale]];
As mentioned above in 1st and 3rd i am not the desired output. Any idea what i am doing wrong here.
The only numbers that do not have the expected output have a comma instead of a period and a period instead of a comma in the input. Try replacing that and see if it works as some locals use different decimal separators.
I propose you to specify NumberFormatters decimalSeparator yourself and in input string replace , and . with same character you used in decimalSeparator.
import Foundation
let formatter = NumberFormatter()
formatter.numberStyle = .decimal
func cleanNumberString(with string: String) -> String {
let knownDecimalSeparators = [",", "."]
let localSeparator = formatter.decimalSeparator ?? "."
var cleanString = string;
for separator in knownDecimalSeparators {
cleanString = cleanString.replacingOccurrences(of: separator, with: localSeparator)
}
return cleanString
}
func number(with string: String) -> Double {
let cleanString = cleanNumberString(with: string)
let number = formatter.number(from: cleanString)
return number?.doubleValue ?? 0
}
let string1 = "14,4"
let string2 = "14.4"
let cleanString1 = cleanNumberString(with: string1)
let cleanString2 = cleanNumberString(with: string2)
let number1 = number(with: string1)
let number2 = number(with: string2)
Same in Objective-C
#interface CleanNumberFormatter ()
#property (nonatomic) NSNumberFormatter *formatter;
#end
#implementation CleanNumberFormatter
- (instancetype)init
{
self = [super init];
if (self) {
self.formatter = [NSNumberFormatter new];
self.formatter.numberStyle = NSNumberFormatterDecimalStyle;
}
return self;
}
- (NSString *)cleanNumberStringWithString:(NSString *)string
{
NSArray *knownDecimalSeparators = #[#",", #"."];
NSString *localSeparator = self.formatter.decimalSeparator ?: #",";
NSString *cleanString = [string copy];
for (NSString *separator in knownDecimalSeparators) {
cleanString = [cleanString stringByReplacingOccurrencesOfString:separator withString:localSeparator];
}
return cleanString;
}
- (double)numberWithString:(NSString *)string
{
NSString *cleanString = [self cleanNumberStringWithString:string];
double number = [self.formatter numberFromString:cleanString].doubleValue;
return number;
}
- (void)foo
{
NSString *string1 = #"14.4";
NSString *string2 = #"14,4";
NSString *cleanString1 = [self cleanNumberStringWithString:string1];
NSString *cleanString2 = [self cleanNumberStringWithString:string2];
double number1 = [self numberWithString:string1];
double number2 = [self numberWithString:string2];
}
#end

ios numberformatter currency remove trailing decimals if 0

I want to format my number into a currency string. These are the following cases
25.00 => $25
25.43 => $25.43
25.4 => $25.40
0.00 -> $0
Is there a way to do this in NSNumberFormatter?
This is my code right now:
NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
[fmt setNumberStyle:NSNumberFormatterCurrencyStyle];
[fmt setCurrencyCode:#"USD"];
However that fails for my first and last examples.
I also tried:
NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
[fmt setPositiveFormat:#"$0.##"];
However that fails for my third case. Any suggestions?
Change the number of fraction digits based upon whether or not the number is whole.
- (NSString *)stringFromNumber:(NSNumber *)number
{
BOOL isWholeNumber = (roundf(number.doubleValue) == number.doubleValue);
self.currencyNumberFormatter.maximumFractionDigits = self.currencyNumberFormatter.minimumFractionDigits = isWholeNumber ? 0 : 2;
NSString *str = [self.currencyNumberFormatter stringFromNumber:number];
return str;
}
I don't think there's a way to do this using a plain NSNumberFormatter. You could set the minimum and maximum fraction digits to 0 just for formatting integers in a subclass of NSNumberFormatter:
#interface MyCurrencyFormatter : NSNumberFormatter
#end
#implementation MyCurrencyFormatter
- (id)init {
if ((self = [super init])) {
[self setNumberStyle:NSNumberFormatterCurrencyStyle]];
[self setCurrencyCode:#"USD"];
}
return self;
}
- (NSString *)stringFromNumber:(NSNumber *)aNumber {
NSInteger minimumFractionDigits = [self minimumFractionDigits];
NSInteger maximumFractionDigits = [self maximumFractionDigits];
if ([self isInteger:aNumber]) {
[self setMinimumFractionDigits:0];
[self setMaximumFractionDigits:0];
}
NSString *formattedNumber = [super stringFromNumber:aNumber];
[self setMinimumFractionDigits:minimumFractionDigits];
[self setMaximumFractionDigits:maximumFractionDigits];
return formattedNumber;
}
- (BOOL)isInteger:(NSNumber *)aNumber {
NSDecimal decimalValue = aNumber.decimalValue;
NSDecimalRound(&decimalValue, &decimalValue, 0, NSRoundDown);
NSDecimalNumber *roundedValue = [[NSDecimalNumber alloc] initWithDecimal:decimalValue]
return [aNumber isEqualToNumber:roundedValue];
}
#end
This should handle international number formats as well.
Credit to this post for determining if a number is an integer.
I am using the following solution in Swift. It is based on jowie's answer except I do not want to change maximumFractionDigits if my number is not whole. In some countries more than 2 digits are used for prices.
if(price==price.decimalNumberByRoundingAccordingToBehavior(nil))
{
numberFormatter.maximumFractionDigits=0
numberFormatter.minimumFractionDigits=0
}
let priceStr = numberFormatter.stringFromNumber(price)!
A "swifty" way to achieve the desired result, but remain flexible is to set a range by setting the minimum and maximum fraction digits to show:
let price: NSDecimalNumber // 299.0
let priceLocale: Locale // .current
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.locale = priceLocale
formatter.maximumFractionDigits = 2
formatter.minimumFractionDigits = 0
let result = formatter.string(from: price) ?? "" // 299 $

Format a UITextField for currency

I have a UITextField on my aplication that receives only numeric input from the user. This numeric input represents currency and have the default value of 0.00.
I would like to create something like a mask to format the UITextField as the user enter the numbers. For example:
9 becomes $0,09
99 becomes $0,99
999 becomes $999,99
The code below works great, but as I'm using integer and float values the app will eventually display wrong values afeter a certain point. For example:
999999999 becomes 100000000
That happens because flot and integer aren't precise enough and NSDEcimalNumber should be used. The point is that I can't figure out how to replace my integers and float values to NSDecimalNumber ones.
Does anyone could give me a hand to solve this? I spend some time searching the web for a solution but didn't find that suits my needs and tons of people with the same problem.
Heres the code:
-(BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField.tag == 1){
NSString *cleanCentString = [[textField.text componentsSeparatedByCharactersInSet: [[NSCharacterSet decimalDigitCharacterSet] invertedSet]] componentsJoinedByString:#""];
NSInteger centValue= cleanCentString.integerValue;
if (string.length > 0)
{
centValue = centValue * 10 + string.integerValue;
}
else
{
centValue = centValue / 10;
}
NSNumber *formatedValue;
formatedValue = [[NSNumber alloc] initWithFloat:(float)centValue / 100.0f];
NSNumberFormatter *_currencyFormatter = [[NSNumberFormatter alloc] init];
[_currencyFormatter setNumberStyle:NSNumberFormatterCurrencyStyle];
textField.text = [_currencyFormatter stringFromNumber:formatedValue];
return NO;
}
if (textField.tag == 2){
// Nothing for now
}
return YES;
}
Implement UITextFieldDelegate and add next methods:
Swift:
let currencySign = "$"
// Adds $ before the text, e.g. "1" -> "$1" and allows "." and ","
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool
{
var value = textField.text
var newString = (textField.text as NSString).stringByReplacingCharactersInRange(range, withString: string)
var components = newString.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "1234567890,.").invertedSet)
var decimalString = "".join(components) as NSString
var length = decimalString.length
if length > 0 {
value = "\(currencySign)\(decimalString)"
}
else {
value = ""
}
textField.text = value
}
// Formats final value using current locale, e.g. "130,50" -> "$130", "120.70" -> "$120.70", "5" -> "$5.00"
func textFieldDidEndEditing(textField: UITextField) {
var value = textField.text
var components = value.componentsSeparatedByCharactersInSet(NSCharacterSet(charactersInString: "1234567890,.").invertedSet)
var decimalString = "".join(components) as NSString
let number = NSDecimalNumber(string: decimalString, locale:NSLocale.currentLocale())
var formatter = NSNumberFormatter()
formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
formatter.locale = NSLocale.currentLocale()
if let formatedValue = formatter.stringFromNumber(number) {
textField.text = formatedValue
}
else {
textField.text = ""
}
}
You can convert integer or double/float value to string by following:
NSString *str = [#(myInt) stringValue];
NSString *str1 = [[NSNumber numberWithFloat:myFloat] stringValue];
After that you can convert string to NSDecimalNumber by many ways. Like:
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithString:#"100.1"];
NSLog(#"%#", number);
NSDecimalNumber *num = [NSDecimalNumber decimalNumberWithString:#"100.1" locale:NSLocale.currentLocale];
NSLog(#"%#",num);
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init];
[formatter setNumberStyle:NSNumberFormatterDecimalStyle];
[formatter setLocale:[NSLocale currentLocale]];
NSLog(#"%#", [formatter stringFromNumber:number]);
NSNumberFormatter will help you with the right formatting. Please read apples page for NSDecimalNumber and NSNumberFormatter.
NSNumberFormatter contains a section named"Configuring the Format of Currency". I didn't try it, but it seems something that can help you.
Let me know if this helps.. :)

Stop Float value rounding off in objective c

I have to prevent the value from rounding off after the decimal.
Here is the code I use :
NSNumberFormatter* nf = [[[NSNumberFormatter alloc] init] autorelease];
nf.positiveFormat = #"0.###";
NSString* trimmedValue = [nf stringFromNumber: [NSNumber numberWithFloat:[exRateLabel doubleValue]*amount]];
trimmedValue = [trimmedValue substringToIndex:[trimmedValue length]-1];
In this case, if I multiply 1000 * 50.1234 I'm getting 50123.3984, but it should be 50123.4.
NSLog(#".2f",50.1234*1000);
For this case it's showing the correct value but for
NSLog(#".2f",50.1234*123);
it is rounding off the actual value, which is 6165.1782, to 6165.18.
Just use double instead of float and a proper rounding rule:
NSNumberFormatter* nf = [[NSNumberFormatter alloc] init];
nf.positiveFormat = #"0.###";
nf.roundingMode = NSNumberFormatterRoundFloor;
NSString* trimmedValue = [nf stringFromNumber: [NSNumber numberWithDouble:50.1234*123]];
NSLog(#"trimmedValue: %#", trimmedValue);
And the result is:
trimmedValue: 6165.178
If the mathematics is required to be precise, I'd suggest using an NSDecimalNumber.
NSDecimalNumber *myNumber = [[NSDecimalNumber alloc] initWithMantissa:501234 exponent:-4 isNegative:NO]];
NSDecimalNumber *answer = [self multiplyDecimalNumber:myNumber with:[NSDecimalNumber decimalNumberWithMantissa:1000 exponent:0 isNegative:NO];
NSLog(#"Answer: %g", floor([answer doubleValue]));
I made a quick wrapper for the multiplication, I never wanted an exception, your needs may be different:
-(NSDecimalNumber *) multiplyDecimalNumber:(NSDecimalNumber *) lhs with:(NSDecimalNumber *) rhs {
NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:NSDecimalNoScale raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
return [lhs decimalNumberByMultiplyingBy:rhs withBehavior:handler];
}
They are both correct.
First, I believe you have a typo - you're missing the %.
NSLog(#"%.2f", 50.1234*1000); // same as #"%.2f", 50,123.4 = #"50123.4"
the math leaves you with a clean 1/10th, even though you are asking for 2 decimal places to be printed.
NSLog(#"%.2f",50.1234*123); // same as #"%.2f", 5,161.1782 = #"5161.18"
you are asking for two decimal numbers and rounding up is the default behavior.
It sounds like the formatting you actually want to use is:
NSLog(#"%.1f", number);
or if you want a forced, zero-padded two digits, use
NSLog(#"%.02", number); // first case would come out #"50123.40"
this will force all trailing zeros to be printed
you are probably using a 'double' representation, cast the number to a float or you can use your own policy for truncation using functions like:
float roundUp (float value, int digits) {
int mod = pow(10, digits);
float roundedUp = value;
if (mod != 0) {
roundedUp = ceilf(value * mod) / mod;
}
return roundedUp;
}
float roundDown (float value, int digits) {
int mod = pow(10, digits);
float roundedDown = value;
if (mod != 0) {
roundedDown = floorf(value * mod) / mod;
}
return roundedDown;
}
float nearestf (float value, int digits) {
int mod = pow(10, digits);
float nearest = value;
if (mod != 0) {
nearest = floorf(value*mod + 0.5) / mod;
}
return nearest;
}
'roundUp' should be the one you need, or try with the more generic 'nearestf'
For me it was requirement to show atleast two decimal and maximum decimal number.
Following code did worked for me.
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:2];
[numberFormatter setMinimumFractionDigits:2];
[numberFormatter setRoundingMode:NSNumberFormatterRoundDown];
NSString *num = #"123456.019";
NSString *stringFromNumber = [numberFormatter stringFromNumber:[numberFormatter numberFromString:num]];
NSLog(#"check this %#", stringFromNumber);

Resources