Is there a way to determine if a float has non zero decimal values? I'd like to avoid a string conversion then splitting on any decimal. But not sure if there is some other way.
2 Answers
You can't.
Floating point variables (both Float
and Double
) store values with a limited precesion. Very rarely will a number will be stored as .000...
.
See Is floating point math broken?
The work around:
First, determine an epsilon value you deem to be "as far from .000...
as a number can be for me to still consider it 'whole'". This number will depend on your problem domain. Suppose I values within .001
are acceptably "whole"
Secondly, determine what the closest whole number by rounding it.
Finally, subtract the original value from its rounded counterpart, and check if the difference is less within the epsilon value.
import Foundation
extension Double {
private static var epsilon = 0.0001
var isWhole: Bool { return abs(self - round(self)) < Double.epsilon }
}
let input = 1.0
print(input.isWhole)
This is very similar to the recommended technique for comparing equality of two Float/Double
values.
In Swift 3.0
Since Swift 3.0 is fast approaching, I'll include an answer for it, even if the question specifically covers Swift 2.
In Swift 3.0 Enhanced Floating Point Protocols has been implemented, making it easier to work with floating point arithmetics. We can, e.g. use the isEqual
method, which implements the IEEE 754 equality predicate, for comparing two floating point numbers
import Foundation // for access to round function
extension Double {
var isAsGoodAsIntegerValuedAsItGets: Bool {
return isEqual(to: round(self))
}
}
var input = 1.01
print(input.isAsGoodAsIntegerValuedAsItGets) // false
input = 1
print(input.isAsGoodAsIntegerValuedAsItGets) // true
/* increase to least representable value that compares
greater than current `self` */
input = input.nextUp
print(input.isAsGoodAsIntegerValuedAsItGets) // false
/* decrease to the greatest representable value that
compares less than current `self` */
input = input.nextDown
print(input.isAsGoodAsIntegerValuedAsItGets) // true
-
`isEqual` is awesome! Nice! – Alexander Jul 17 '16 at 15:40