There are very different ways of displaying numbers, for example:
16666,67
16666.67
16.666,67
16.666.67
Those are all valid numbers for different regions and / or countries.
In our usecase we have to use following representation:
16.666.67
Because
Its easier to see how big the number is using the thousands seperator
We needed to prevent wrong user inputs so we are replacing all commas with a period
Though, for a numberformatter with a period as decimal sperator 16.666.67 is not a valid number:
self.numberFormatter = NumberFormatter()
self.numberFormatter.numberStyle = .decimal;
self.numberFormatter.minimumFractionDigits = 0;
self.numberFormatter.maximumFractionDigits = 2;
self.numberFormatter.decimalSeparator = ".";
print(self.numberFormatter.number(from: "16.666.67");
which is resulting in nil. Why is that an invalid number? And how can I solve that problem?'
EDIT
Following test:
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal;
numberFormatter.minimumFractionDigits = 0;
numberFormatter.maximumFractionDigits = 2;
numberFormatter.groupingSeparator = ".";
numberFormatter.decimalSeparator = ".";
print(numberFormatter.number(from: "16666"));
print(numberFormatter.number(from: "16666,67"));
print(numberFormatter.number(from: "16666.67"));
print(numberFormatter.number(from: "16.666"));
print(numberFormatter.number(from: "16.666,67"));
print(numberFormatter.number(from: "16.666.67"));
output is:
Optional(16666)
nil
Optional(16666.67)
Optional(16666)
nil
nil
The issue is that the String 16.667.67 is no less an invalid number as This.is.a.number.00.
You need to make your String variable be something valid.
EDIT:
Based on the comments this sounds like a language behavior issue (Java versus Swift).
I'm seeing other comments on handling this, but to me, it looks like it gets down to how the Swift NumberFormatter automatically handles a String input with multiple decimal points. Unlike (some) other languages, you may need to do some pre-formatting of the string before calling NumberFormatter.
Related
let balance = "2.477854178281608e-06"
// I have to convert this exponential value in Decimal
/* Already tried the below-mentioned solution, but not working */
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
let finalNumber = numberFormatter.number(from: balance)
print(finalNumber!)
Value is printing "2.477854178281608e-06\n"
Any help will be appreciated.
let balance = "2.477854178281608e-06"
// I have to convert this exponential value in Decimal
This is not an exponential value. This is a string that represents a number using exponential format. You seem to want a string representing the same number in a different format. The important thing here is that neither string is "the value." The value is the same regardless of representation (or approximately the same if the representation is limited).
So first you need the value represented by the string. To do that, convert it to a Double.
let value = Double(balance)!
Now, you say you want to convert that to a string in decimal format (I assume you mean 0.000...). So you need a formatter:
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 20
let string = numberFormatter.string(for: value)!
print(string) // 0.00000247785417828161
You'll note that this value is slightly different than the previous value. That's because there are rounding errors when dealing with values this small.
If all of these base-10 digits are important, you can work with the Decimal type rather than Double. This avoids decimal/binary rounding, but is less convenient and slower for some kinds of math. If this is a type of currency that is expressed in base-10 units (which is basically all of them), you always want to work with Decimal and never with Double.
let balance = "2.477854178281608e-06"
let value = Decimal(string: balance)!
let numberFormatter = NumberFormatter()
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 21
let string = numberFormatter.string(for: value)!
print(string) // 0.000002477854178281608
Try to find a way to convert plain English number (e.g., One, Two...) to Int (e.g., 1, 2...)
I know that there is way to convert from Int to English using
numberFormatter:NumberFormatter = NumberFormatter()
numberFormatter.numberStyle = NumberFormatter.Style.spellOut
var string = numberFormatter.string(from: 3) // "three"
Is there any reverse way of converting this?
I am trying to avoid using array of String like ["One", "Two"..]
Number formatters work in both directions, so you can just use:
let num = numberFormatter.number(from: string)
But you'll need to take some care to make sure it exactly matches the output of the forward direction. "three" will translate to 3, but "Three" won't.
As Sulthan notes, this is absolutely sensitive to the locale of the formatter (which you can set to be different than the user's locale if that's necessary). It is strongly assuming that the input and output from the same formatter match.
I have a word that is being displayed into a label. Could I program it, where it will only show the last 2 characters of the word, or the the first 3 only? How can I do this?
Swift's string APIs can be a little confusing. You get access to the characters of a string via its characters property, on which you can then use prefix() or suffix() to get the substring you want. That subset of characters needs to be converted back to a String:
let str = "Hello, world!"
// first three characters:
let prefixSubstring = String(str.characters.prefix(3))
// last two characters:
let suffixSubstring = String(str.characters.suffix(2))
I agree it is definitely confusing working with String indexing in Swift and they have changed a little bit from Swift 1 to 2 making googling a bit of a challenge but it can actually be quite simple once you get a hang of the methods. You basically need to make it into a two-step process:
1) Find the index you need
2) Advance from there
For example:
let sampleString = "HelloWorld"
let lastThreeindex = sampleString.endIndex.advancedBy(-3)
sampleString.substringFromIndex(lastThreeindex) //prints rld
let secondIndex = sampleString.startIndex.advancedBy(2)
sampleString.substringToIndex(secondIndex) //prints He
I am working on an application that needs to do some displaying and calculating of Double types in Swift. The struct that I created takes a Double as a parameter, and since it also displays it, I would like to keep the trailing zero at the end of the value. However, I cannot seem to keep the trailing zero from being truncated.
Here is what I have been trying in a Playground:
let numberString = "-3.60"
// "3.60"
let positiveString = numberString.stringByReplacingOccurrencesOfString("-", withString: "", options: nil, range: nil)
// 3.6
let positiveDouble = (positiveString as NSString).doubleValue
// "3.60"
let positiveDoubleString = NSString(format: "%0.02f", positiveDouble)
// 3.6
let positiveDoubleWithZeros = positiveDoubleString.doubleValue
I keep getting 3.6 as the result, no matter what I try. What is the obvious part of the conversion that I am missing?
You have to use NSNumberFormatter:
let formatter = NSNumberFormatter()
formatter.minimumFractionDigits = 2
formatter.maximumFractionDigits = 3
println(formatter.stringFromNumber(1.0000))
println(formatter.stringFromNumber(1.2345))
This example will print 1.00 for the first case and 1.234 for the second, the number of minimum and maximum decimal places can be adjust as you need.
I Hope that helps you!
Here's a real-life example; hand-written .proto file extract:
message StatsResponse {
optional int64 gets = 1;
optional int64 cache_hits = 12;
optional int64 fills = 2;
optional uint64 total_alloc = 3;
optional CacheStats main_cache = 4;
optional CacheStats hot_cache = 5;
optional int64 server_in = 6;
optional int64 loads = 8;
optional int64 peer_loads = 9;
optional int64 peer_errors = 10;
optional int64 local_loads = 11;
}
I understand everything about it except how the programmer who wrote it chose the tag numbers he was going to use.
The official documentation just notes how these tags are shifted around and encoded to compose a wire type identifier. Yet, in the example above, several fields of the same data type have different tag numbers.
My question is; how do I choose tag numbers if I was going to write a .proto file from scratch?
The number is just an alternative way to identify the field, other than its name. The encoding uses numbers rather than names because they take less space and time to encode. It doesn't matter what number you use as long as you don't change the number later (although, lower numbers take less space on the wire).
Usually, people simply assign numbers sequentially starting from 1. In your example proto, cache_hits is probably a new field that was added after all the others, which is why its number appears "out-of-order".