1

I am trying to accurately represent floating point numbers in Swift. Let's say that we have a number let doubleNumber = 16.756. The problem with this is that the actual number is something like 16.7560009. More over, on different phone it is 16.7559991 for example, because of processor inequalities. Fixed point arithmetic should be the answer to this kind of problems, but I have no idea how to tackle it in Swift. To be honest, nor in other languages. So how do I create fixed point representations of floating point numbers in Swift?

The reason I am asking is that when simulating physics accurately across devices the tiny differences in the value of floating point number can cause completely different physics simulations.

Sapphire_Brick
  • 1,560
  • 12
  • 26
potato
  • 4,479
  • 7
  • 42
  • 99
  • What are you actually trying to achieve? What is the problem that you are trying to solve? Do you need to accurately represent 1.0 / 3.0? – gnasher729 Nov 18 '15 at 10:48
  • I edited my question. – potato Nov 18 '15 at 11:04
  • 1
    "I am trying to accurately represent floating point numbers in Swift." – the Float and Double types already do that. Are you confusing floating-point numbers with real numbers? – The Paramagnetic Croissant Nov 18 '15 at 12:15
  • Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – user207421 Oct 28 '19 at 01:09
  • @user207421 Not a duplicate. This is asking "how do I do fixpoint arithmetic in swift" and the floating-point stuff is just backstory. – pppery Oct 28 '19 at 02:33

2 Answers2

5

The numbers that you gave indicate that you are using Float, and not Double. Float only has about 6 digits precision, Double has about 15. And remember that CGFloat is either Float or Double, so don't use that.

Swift uses IEEE 754 standard floating point arithmetic. There shouldn't be any difference between different processors as long as you use Double consistently.

Now here comes a very crucial point: If slight differences between floating point arithmetic on different processors produce completely different simulations, then neither simulation has anything to do with reality and is therefore completely useless. Or they both show one of many possible outcomes, and then again it makes no difference which one you show.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • 1
    Couldn't a slight difference at the start produce very different outcomes in a simulation due to accumulation over time (like calculations each frame, with rounding/truncation)? – Ben Stahl Jan 29 '19 at 02:12
-1

funny experiment

import Foundation

let f1: Float = 0x1p-149
f1.isZero                       // false
let f0: Float = 0x1p-150
f0.isZero                       // true   
Float(f1 / 2) == Float(f1 / 3)  // true ??? what ??? f1 is zero?

let d1 = 0x1p-1074
d1.isZero                       // false
let d0 = 0x1p-1075
d0.isZero                       // true
d1 / 2 == d1 / 3                // true

print("value of Float next to 0 is \(f1) or as Double \(Double(f1))")
print("value of Double next to 0 is \(d1)")

/*

value of Float next to 0 is 1.4013e-45 or as Double 1.40129846432482e-45
value of Double next to 0 is 4.94065645841247e-324

*/

i recommend for everybody who need to perform floating point calculations What Every Computer Scientist Should Know About Floating-Point Arithmetic

one example how proper algorithm can reduce an error

import Foundation

var arr: [Float] = []
for i in 0...100 {
    arr.append(Float(random()))
}

let sum1 = arr.reduce(0.0) { $0 + $1 }

var sum2 = arr[0]
var c:Float = 0.0
for j in 1..<arr.count {
    let y: Float = arr[j] - c
    let t: Float = sum2 + y
    c = t - sum2 - y
    sum2 = t
}
print(sum1, sum2, "and the 'small' difference is:", sum2 - sum1)
// 1.18466e+11 1.18466e+11 and the 'small' difference is: 8192.0

// what do you thing, which one is more precise ?
// sum1 or sum2 ????

// lets try the same with naive Double approach
let sum3 = arr.map{ Double($0) }.reduce(0.0) { $0 + $1 }
print(Double(sum1)-sum3)    // -11268.0
print(Double(sum2)-sum3)    // -3076.0
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • 1
    Could you add some details of why this should work? Code-only answers are not very useful and are subject to deletion. – Cristik Nov 18 '15 at 16:32
  • @Cristik it is not an answer how to perform fixed point arithmetic. this snippets can answer the questions like why my iteration never stopped or similar. look at line d1 / 2 == d1 / 3 is true even though the d1 (as you can see in print out) is NOT zero – user3441734 Nov 18 '15 at 16:40
  • 1
    in this case please update the answer and add explanations regarding the experiment results, in the current form your answer is not very helpful to the asker. – Cristik Nov 18 '15 at 16:53
  • @Cristik does the second example better explain why the proper algorithm is so important? the precision even of Float numbers are good enough when properly used in code. the two algorithms in my example do the same. the first one is naive sum1, the second one is more precise sum2. see the difference there! even though i receive a lot of down votes here, somebody who need perform accurate calculation can see my example valuable. computation in physic is about analyzing possible errors, not about fixed floating point calculations – user3441734 Nov 18 '15 at 18:24
  • 1
    I think the original revision of your answer is responsible for the downvotes - "funny experiment" followed by some code. The explanations you added via the comments are valuable, you should also add those to the answer too. People don't always read the comments. – Cristik Nov 18 '15 at 19:07