user500 user500 - 5 months ago 29
Swift Question

How to get smallest value (stride) for particular number type in Swift?

How to get smallest value (stride) for particular number type in Swift? I mean, the shortest non-zero stride.
For example

1
for
Int
,
0.00...001
for
Double
etc...

Answer

This has been partially addressed in separate comments already, but to bring it all together...

For integer types:

The smallest possible increment between distinct values is 1. This is part of the definition of an integer, so it's such a foundational aspect of the type that there isn't (and needn't be) a special API for finding it.

(One can argue that successor constitutes such an API. But one can also argue that using successor where you could just use 1 makes your code much less readable.)

For floating-point types:

There is no one smallest possible increment. Because floating-point types use an exponent-based representation, the spacing between representable floating-point numbers varies with the exponent, as illustrated in this number line:

density of floating point numbers That image comes from What Every Computer Scientist Should Know About Floating-Point Arithmetic, an essential read for, well, everyone using floating-point numbers. You can read more about the concept in Wikipedia's pages for Unit in the Last Place and Machine Epsilon. Exploring Binary also has a good entry-level read on floating-point spacing.

Back to Swift — The Float and Double types conform to the FloatingPoint protocol (in Swift 3, currently in beta). This defines the features of IEEE 754 floating point formats, which includes both:

  • The Unit in the Last Place, or ulp, which tells you the increment between a number and the next greater representable number (but for some edge cases). This is related to, but not the same as, machine epsilon, since it scales with value. (ulpOfOne is the same as what other libraries call machine epsilon.)

  • nextUp and nextDown, which tell you the closest greater or lesser representable numbers.

Here's an example (conveniently showing that for 32-bit Float, the minimum increment gets bigger than one sooner than you might think):

let ichi: Float = 1.0
ichi.ulp    // -> 1.192093e-07
ichi.nextUp // -> 1.00000012

let man: Float = 10_000
man.ulp    // -> 10000
man.nextUp // -> 10000.001

let oku: Float = 100_000_000
oku.ulp    // -> 8
oku.nextUp // -> 100000008.0

In Swift 2, there's no FloatingPoint protocol, but you can make use of the equivalent POSIX constants/functions imported from C: FLT_EPSILON and DBL_EPSILON are defined as the difference between 1.0 and the next representable value, and the nextafter functions find the increment at any value.

Comments