How to get exact value from NSNumberFormatter? - ios

From the code below I want convertedN to be to be 99999999 but instead I get 99999998. The problem is that there is a rounding error before I set n. What can I do to get the result I want?
let amount = ".99999999"
let tmpFormatter = NSNumberFormatter()
tmpFormatter.maximumFractionDigits = 8
let n = tmpFormatter.numberFromString(amount)
let decimalAmount = NSDecimalNumber(decimal: n!.decimalValue)
let convertedN = (decimalAmount.decimalNumberByMultiplyingBy(NSDecimalNumber(unsignedLongLong: 100000000))).unsignedLongLongValue

Use doubleValue instead. NSDecimalNumber is rounding the numbers.
let amount = ".99999999"
let tmpFormatter = NSNumberFormatter()
tmpFormatter.maximumFractionDigits = 8
let n = tmpFormatter.numberFromString(amount)
let doubleValue = n!.doubleValue
let convertedN = doubleValue * 100000000

Try like this:
let amount = ".99999999"
let decimalAmount = NSDecimalNumber(string: amount)
let convertedN = decimalAmount.decimalNumberByMultiplyingBy(NSDecimalNumber(string: "100000000")).unsignedLongLongValue // 99,999,999

Related

Convert currency formatter to double swift

For some reason, I can't convert the Price string to double.
When I do it always returns nil.
func calculateAirfare(checkedBags: Int, distance: Int, travelers: Int) {
let bagsPrices = Double(checkedBags * 25)
let mileCosts = Double(distance) * 0.10
let price = (bagsPrices + mileCosts) * Double(travelers)
/// Format price
let currencyFormatter = NumberFormatter()
currencyFormatter.numberStyle = .currency
let priceString = currencyFormatter.string(from: NSNumber(value: price))
print(priceString) -> "Optional("$750.00")"
if let double = Double(priceString) {
print(double) -> nil
}
}
You can use your same formatter to go back to a number like so:
let number = currencyFormatter.number(from: priceString)
and get the doubleValue like:
let numberDouble = number.doubleValue
The price is already double from the line
let price = (bagsPrices + mileCosts) * Double(travelers)
thus no need to convert it to double.
The code below will return a string with a $ symbol
currencyFormatter.string(from: NSNumber(value: price))
To get a double from that string then you need to remove the $ symbol
which you can do using removeFirst()
priceString?.removeFirst()
After that, the string can be converted to Double.
The complete code is:
func calculateAirfare(checkedBags: Int, distance: Int, travelers: Int) {
let bagsPrices = Double(checkedBags * 25)
let mileCosts = Double(distance) * 0.10
let price = (bagsPrices + mileCosts) * Double(travelers)
/// Format price
let currencyFormatter = NumberFormatter()
currencyFormatter.numberStyle = .currency
var priceString = currencyFormatter.string(for: price)
priceString?.removeFirst()
print(priceString!)
if let double = Double(priceString!) {
print(double)
}
}

Choosing units with MeasurementFormatter

This is similar to a question I asked yesterday but the answer I got doesn't seem to work in this case.
I'm getting altitude values in meters from Core Location. I want to display these in a localized form. As an example, the altitude where I am right now is 1839m above sea level. This should be displayed as 6033 feet. The best I can do with MeasurementFormatter is "1.143 mi".
let meters : Double = 1839
let metersMeasurement = Measurement(value: meters, unit: UnitLength.meters)
let measurementFormatter = MeasurementFormatter()
measurementFormatter.locale = Locale(identifier: "en_US")
let localizedString = measurementFormatter.string(from: metersMeasurement)
The .naturalScale option that answered my previous question doesn't help here. I think this is a limitation of the framework, but I wonder if anyone has a workaround for now.
You just need to convert your UnitLength from meters to feet. You can also create a custom US measurement formatter to display it as needed:
extension Measurement where UnitType == UnitLength {
private static let usFormatted: MeasurementFormatter = {
let formatter = MeasurementFormatter()
formatter.locale = Locale(identifier: "en_US")
formatter.unitOptions = .providedUnit
formatter.numberFormatter.maximumFractionDigits = 0
formatter.unitStyle = .long
return formatter
}()
var usFormatted: String { Measurement.usFormatted.string(from: self) }
}
Playground
let value: Double = 1839
let meters: Measurement<UnitLength> = .init(value: value, unit: .meters)
let feet = meters.converted(to: .feet)
let formatted = feet.usFormatted
print(formatted) // "6,033 feet"\n
I think you are correct there's no way to specify this kind of context. You could do something like:
extension MeasurementFormatter
{
func altitudeString(from measurement: Measurement<UnitLength>) -> String
{
var measurement = measurement
let unitOptions = self.unitOptions
let unitStyle = self.unitStyle
self.unitOptions = .naturalScale
self.unitStyle = .long
var string = self.string(from: measurement)
if string.contains(self.string(from: UnitLength.miles))
{
self.unitStyle = unitStyle
measurement.convert(to: UnitLength.feet)
self.unitOptions = .providedUnit
string = self.string(from: measurement)
}
else if string.contains(self.string(from: UnitLength.kilometers))
{
self.unitStyle = unitStyle
measurement.convert(to: UnitLength.meters)
self.unitOptions = .providedUnit
string = self.string(from: measurement)
}
else
{
self.unitStyle = unitStyle
string = self.string(from: measurement)
}
self.unitOptions = unitOptions
return string
}
}
Maybe there are other culturally specific ways of measuring elevation, but this would seem better than miles and kilometers.

How to display the string without 0

I try to eliminate the 0 at the end of string. right now what i have is (Return "2101999.0000")
let point = newObject["PtsBal"] as! String
i use
NSNumberRFormatter()
but i dont know where i did wrong. i need to display it back in this as a string.
self.detailArr = ["\((self.userInfo!["FirstName"] as! String).capitalizedString) \((self.userInfo!["LastName"] as! String).capitalizedString)", point, ""]
try this
let point = newObject["PtsBal"] as! String
let formatter = NSNumberFormatter()
formatter.numberStyle = .DecimalStyle
if let number = formatter.numberFromString(point) {
// number is an instance of NSNumber
point = String(number.integerValue)
}
you get the output as
finally append the string where you need
self.detailArr = ["\((self.userInfo!["FirstName"] as! String).capitalizedString) \((self.userInfo!["LastName"] as! String).capitalizedString)", point, ""]
You can simply remove all characters after (.) dot
var str = "2101999.0000"
if let dotRange = str.rangeOfString(".") {
str.removeRange(dotRange.startIndex..<str.endIndex)
}
Use this single line of Code
let number : Int = NSString(string: YourString).integerValue
Assuming point is always a string representing a floating point value you could use
let point = "2101999.0000"
let number = "\(Int(Double(point)!))"
let string = "2101999.0000"
let result = string.characters.split{$0 == "."}.map(String.init)
print (result[0])

swift 2 convert int to numberFromString as String

I am new in swift and I want to write the number with commas
NSNumberFormatter().numberFromString("123456789")) as! String
I have error Cannot convert value of type 'Int' to expected argument type 'String'.
Any help please
Try this one.
let myNumber = 123456789
var numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
numberFormatter.stringFromNumber(myNumber)!
You can set the number of fractions with:
let numberToConvert: Int = 123456789
let numberFormatter = NSNumberFormatter()
numberFormatter.minimumFractionDigits = 2
let convertedNumber = numberFormatter.stringFromNumber(numberToConvert)
prints
"123456789.00"
If you want something like "123,456,789" then add following line after minimumFactionDigits
numberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle
var string= "7890"
var number = Int(string)
If u don't need to specify number of decimal places:
var number: CGFloat = 98888.5555
var string = "\(number)"

Convert Double to Scientific Notation in swift

I am trying to convert a given double into scientific notation, and running into some problems. I cant seem to find much documentation on how to do it either. Currently I am using:
var val = 500
var numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = NSNumberFormatterStyle.ScientificStyle
let number = numberFormatter.numberFromString("\(val)")
println(number as Double?)
// Prints optional(500) instead of optional(5e+2)
What am I doing wrong?
You can set NumberFormatter properties positiveFormat and exponent Symbol to format your string as you want as follow:
let val = 500
let formatter = NumberFormatter()
formatter.numberStyle = .scientific
formatter.positiveFormat = "0.###E+0"
formatter.exponentSymbol = "e"
if let scientificFormatted = formatter.string(for: val) {
print(scientificFormatted) // "5e+2"
}
update: Xcode 9 • Swift 4
You can also create an extension to get a scientific formatted description from Numeric types as follow:
extension Formatter {
static let scientific: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .scientific
formatter.positiveFormat = "0.###E+0"
formatter.exponentSymbol = "e"
return formatter
}()
}
extension Numeric {
var scientificFormatted: String {
return Formatter.scientific.string(for: self) ?? ""
}
}
print(500.scientificFormatted) // "5e+2"
The issue is that you are printing the number... not the formatted number. You are calling numberForString instead of stringForNumber
var val = 500
var numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = NSNumberFormatterStyle.ScientificStyle
let numberString = numberFormatter.stringFromNumber(val)
println(numberString)
Slight modification to the answer by leo-dabus to Xcode 9 Swift 4:
extension Double {
struct Number {
static var formatter = NumberFormatter()
}
var scientificStyle: String {
Number.formatter.numberStyle = .scientific
Number.formatter.positiveFormat = "0.###E+0"
Number.formatter.exponentSymbol = "e"
let number = NSNumber(value: self)
return Number.formatter.string(from :number) ?? description
}
}

Resources