Count number of decimal places in a Float (or Decimal) in Swift
Doing this with Decimal is fairly straightforward, provided you correctly create your Decimal. Decimals are stored as significand * 10^exponent
. significand
is normalized to the smallest integer possible. So for 1230, the significand is 123 and the exponent is 1. For 1.23 the significand is also 123 and the exponent is -2. That leads us to:
extension Decimal {
var significantFractionalDecimalDigits: Int {
return max(-exponent, 0)
}
}
However, you must be very careful constructing your Decimal. If you construct it from a Double, you will already have applied binary rounding errors. So for example:
let n = Decimal(0.111) // 0.11100000000000002048 because you passed a Double
n.significantFractionalDecimalDigits // 20
vs.
let n = Decimal(string: "0.111")!
n.significantFractionalDecimalDigits // 3 what you meant
Keep in mind of course that Decimal has a maximum number of significant digits, so it may still apply rounding.
let n = Decimal(string: "12345678901235678901234567890.1234567890123456789")!
n.significantFractionalDecimalDigits // 9 ("should" be 19)
And if you're walking down this road at all, you really must read the Floating Point Guide and the canonical StackOverflow question: Is floating point math broken?
Count amount of decimal places (Swift)
Try:
let s1 = String(format: "%.19g", 1.2345) // 1.2345
Not sure if swift printf supports '%g' though.
Edit: the 19 is based on the precision of a double, to display all (nonzero) digits, but not get ...0001
at the end. '%g' is the printf format specifier for 'natural' representation of floating point numbers.
Rounding a double value to x number of decimal places in swift
You can use Swift's round
function to accomplish this.
To round a Double
with 3 digits precision, first multiply it by 1000, round it and divide the rounded result by 1000:
let x = 1.23556789
let y = Double(round(1000 * x) / 1000)
print(y) /// 1.236
Unlike any kind of printf(...)
or String(format: ...)
solutions, the result of this operation is still of type Double
.
EDIT:
Regarding the comments that it sometimes does not work, please read this: What Every Programmer Should Know About Floating-Point Arithmetic
Only show my float number to a certain decimal place - Swift
Use a NumberFormatter
(have a look here)
let bmi:Float = (((textfieldInt! * 2.204623) * 0.5) / 1500) * textfield2Int!
let formatter = NumberFormatter()
//Set the min and max number of digits to your liking, make them equal if you want an exact number of digits
formatter.minimumFractionDigits = 1
formatter.maximumFractionDigits = 3
self.total2.text = formatter.string(from: NSNumber(value: bmi)) + " kcal"
How do I extract any number of digits after the decimal point of a Float and convert it to a String in Swift?
You can specify the number of decimal digits, say N
, in your format specifier as %.Nf
, e.g., for 5
decimal digits, %.5f
.
let temp: Float = 3.511054256
let aStr = String(format: "%.5f", temp).componentsSeparatedByString(".").last ?? "Unexpected"
print(aStr) // 51105
Alternatively, for a more dynamic usage, make use of an NSNumberFormatter
:
/* Use NSNumberFormatter to extract specific number
of decimal digits from your float */
func getFractionDigitsFrom(num: Float, inout withFormatter f: NSNumberFormatter,
forNumDigits numDigits: Int) -> String {
f.maximumFractionDigits = numDigits
f.minimumFractionDigits = numDigits
let localeDecSep = f.decimalSeparator
return f.stringFromNumber(num)?.componentsSeparatedByString(localeDecSep).last ?? "Unexpected"
}
/* Example usage */
var temp: Float = 3.511054256
var formatter = NSNumberFormatter()
let aStr = getFractionDigitsFrom(temp, withFormatter: &formatter, forNumDigits: 5)
print(aStr) // 51105
Note that both solutions above will perform rounding; e.g., if var temp: Float = 3.519
, then asking for 2
decimal digits will produce "52"
. If you really intend to treat your float temp
purely as a String
(with no rounding whatsoever), you could solve this using just String
methods, e.g.
/* Just treat input as a string with known format rather than a number */
func getFractionDigitsFrom(num: Float, forNumDigits numDigits: Int) -> String {
guard let foo = String(temp).componentsSeparatedByString(".").last
where foo.characters.count >= numDigits else {
return "Invalid input" // or return nil, for '-> String?' return
}
return foo.substringWithRange(foo.startIndex..<foo.startIndex.advancedBy(numDigits))
}
/* Example usage */
let temp: Float = 3.5199
let aStr = getFractionDigitsFrom(temp, forNumDigits: 2) // 51
Round up double to 2 decimal places
Use a format string to round up to two decimal places and convert the double
to a String
:
let currentRatio = Double (rxCurrentTextField.text!)! / Double (txCurrentTextField.text!)!
railRatioLabelField.text! = String(format: "%.2f", currentRatio)
Example:
let myDouble = 3.141
let doubleStr = String(format: "%.2f", myDouble) // "3.14"
If you want to round up your last decimal place, you could do something like this (thanks Phoen1xUK):
let myDouble = 3.141
let doubleStr = String(format: "%.2f", ceil(myDouble*100)/100) // "3.15"
Rounding a double to 2 decimal places in Swift, XCode 12
You could do it directly inside Text
with the help of string interpolation:
struct ContentView: View {
let decimalNumber = 12.939010
var body: some View {
Text("\(decimalNumber, specifier: "%.2f")")//displays 12.94
}
}
Check if number is decimal with swift
If you round the number down (which you can do by using the floor function), and then subtract it from the original number, you will get the difference between the two.
if (number - floor(number) > 0.000001) { // 0.000001 can be changed depending on the level of precision you need
// decimal
}
Edit --
My original answer recommended calculating the difference between the number and its floored equivalent to see if there were any units after the decimal points. However, as later described, there may be a rounding error which causes the representation of a value in memory to be slightly different than what it's actually meant to be.
For example, 3.0 could be represented as 3.00000000000001, and therefore the number - floor(number) > 0
would return true, even though it should've theoretically returned false as the offset would be 0.00000000000001.
Therefore please use @jessy's answer below.
Related Topics
Unsafemutablepointer in Swift as Replacement for Properly Sized C Array in Obj-C
How to Get Data from Observedobject with Onreceive in Swiftui
Views Compressed by Other Views in Swiftui VStack and List
Include an Extension for a Class Only If iOS11 Is Available
Access Properties via Subscripting in Swift
Swiftui Onhover Doesn't Register Mouse Leaving the Element If Mouse Moves Too Fast
Using Nstimer in Swift Playground
Swift Bindings Won't Work Xcode 6 Beta 5
Reason for Assigning Optional to New Variable in Conditional Statement in Swift
Understanding the Userdefaults Register Method
Changing Color of Button Text and State
Can a Swift Property Wrapper Reference the Owner of the Property Its Wrapping
Simple Clickable Link in Cocoa and Swift
Pass Optional Block or Closure to a Function in Swift
How to Delete from Firebase Database
Creating a Custom Scngeometry Polygon Plane with Scngeometryprimitivetype Polygon Crash/Error
Why Can't I Change Variables in a Protocol Extension Where Self Is a Class