0

I'm having an issue where swift is changing my float value when it's inside a struct.. I dont think this happened on older versions of swift, but it is happening now on 4.1. Code example below... thoughts?

var f = Float(4.111)

print(f) // prints 4.111

struct FloatContainer {
    var f: Float
}

let container = FloatContainer(f: f)

print(container) // prints FloatContainer(f: 4.11100006)
JoeBayLD
  • 939
  • 2
  • 10
  • 25
  • 2
    Related: https://stackoverflow.com/questions/588004/is-floating-point-math-broken – vacawama Aug 24 '18 at 14:09
  • 4
    Possible duplicate of [Is floating point math broken?](https://stackoverflow.com/questions/588004/is-floating-point-math-broken) – ielyamani Aug 24 '18 at 14:15
  • 1
    Also related: https://stackoverflow.com/q/40959254/1187415 – floating point values *inside containers* are (by default) printed with a higher precision. – Martin R Aug 24 '18 at 14:39
  • I've updated my answer, I hope it helps. – ielyamani Aug 28 '18 at 22:57

3 Answers3

2

That's a common rounding error, since binary can't represent some decimal numbers. Have a look here.

Here is an online converter from a decimal to a floating-point representation. As you can see there is an error (6.103515625E-8) due to the conversion:

Floating Point Converter

As to the difference between when you print a float directly, or when you print an object that has a property that is a float, it comes down to the description property of objects that implement the CustomStringConvertible protocol. When the print function wants to print to the console, it invokes _print_unlocked, which is an internal function that has this block:

if case let printableObject as CustomStringConvertible = value {
    printableObject.description.write(to: &target)
    return
}

So you could change your code to this in order to have the expected output:

struct FloatContainer : CustomStringConvertible {
    var description: String {
        get {
            return f.description
        }
    }
    var f: Float
}
ielyamani
  • 17,807
  • 10
  • 55
  • 90
  • 1
    That does not yet explain why the *same value* `f` is printed as 4.111 in one place, and as 4.11100006 in another place. – Martin R Aug 24 '18 at 14:41
0

You should try printing the value inside

print(container.f) // prints 4.111

This is returning what you are storing.

Bhavin Kansagara
  • 2,866
  • 1
  • 16
  • 20
  • Still doesn’t explain why the value is different when referencing the struct vs the actual value. – JoeBayLD Aug 25 '18 at 18:55
0

Swift provides default debug representation for any type and this is the reason Apple documentation

 var f = Float(4.111)

    print(f) // prints 4.111

    print(f.debugDescription) // prints 4.11100006
    print(String(reflecting: f)) // default presentation according to documentation: prints 4.11100006

    struct FloatContainer: CustomStringConvertible {
        var f: Float

        // You can achieve similar output to `print(f)` with conforming
        // to `CustomStringConvertible` and implementing custom 
        // `description` implementation
        var description: String {
            return f.description
        }
    }

    let container = FloatContainer(f: f)
    // After our custom implementation the result of `print` 
    // method is the same to print(f)
    print(container) // prints FloatContainer(f: 4.111)
Robert
  • 3,790
  • 1
  • 27
  • 46