2 Replies
      Latest reply on Mar 14, 2019 3:51 AM by eskimo
      Josedam Level 1 Level 1 (0 points)

        I need to apply .bankers rounding mode but I'm getting some unexpected results when instiating some Decimals, I'm just wondering if this is a bug, expected behavior or what am I missing.

         

        import Foundation
        
        
        extension Decimal {
            
           func rounded(_ scale: Int, _ roundingMode: RoundingMode = .bankers) -> Decimal {
                var toRound = self
                var rounded = Decimal()
                NSDecimalRound(&rounded, &toRound, scale, roundingMode)
                return rounded
            }
        }
        
        
        var a: Decimal = NSDecimalNumber(floatLiteral: 6.422).decimalValue//6.422
        print(a.rounded(1, .bankers))//6.4
        
        
        var b: Decimal = NSDecimalNumber(floatLiteral: 6.4872).decimalValue//6.487200000000001024
        print(b.rounded(2, .bankers))//6.49
        
        
        var c: Decimal = NSDecimalNumber(floatLiteral: 6.997).decimalValue//6.997
        print(c.rounded(2, .bankers))//7
        
        
        var d: Decimal = NSDecimalNumber(floatLiteral: 6.6500).decimalValue//6.65
        print(d.rounded(1, .bankers))//6.6
        
        
        var e: Decimal = NSDecimalNumber(floatLiteral: 7.485).decimalValue//7.485000000000002048
        var e2: Decimal = Decimal(floatLiteral: 7.485)//7.485000000000002048
        print(e.rounded(2, .bankers))//7.49 wrong?, it should be 7.48
        print(e2.rounded(2, .bankers))//7.49 wrong?, it should be 7.48
        
        
        var f: Decimal = NSDecimalNumber(floatLiteral: 6.755000).decimalValue//6.755
        print(f.rounded(2, .bankers))//6.76
        
        
        var g: Decimal = NSDecimalNumber(floatLiteral: 8.995).decimalValue//8.994999999999997952
        var g2: Decimal = Decimal(floatLiteral: 8.995)//8.994999999999997952
        print(g.rounded(2, .bankers))//8.99 wrong?, it should be 9.00
        print(g2.rounded(2, .bankers))//8.99 wrong?, it should be 9.00
        
        
        var h: Decimal = NSDecimalNumber(floatLiteral:  6.6501).decimalValue//6.6501
        print(h.rounded(1, .bankers))//6.7
        
        
        var i: Decimal = NSDecimalNumber(floatLiteral:  7.4852007).decimalValue//7.4852007
        print(i.rounded(2, .bankers))//7.49
        
        
        var j: Decimal = NSDecimalNumber(floatLiteral:  19.57).decimalValue//19.57
        print(j.rounded(2, .bankers))//19.57
        

         

        Why is 7.485 actually 7.485000000000002048?

        Why is 8.995 actually 8.994999999999997952?

         

        Thank you in advance!

        • Re: Decimal precision correct?
          Claude31 Level 8 Level 8 (5,565 points)

          Problem when you transform first to Float, you have a precision effect ; hence the value is closer to 7.49 than 7.48.

          So, the halfway effect does not play.

           

          That seems to be normal behavior.

            • Re: Decimal precision correct?
              eskimo Apple Staff Apple Staff (10,875 points)

              Problem when you transform first to Float, you have a precision effect

              Yep.  Consider this:

              let n: Decimal = 7485
              let d: Decimal = 1000
              let e = n / d
              print(e)    // -> 7.485
              let r = e.rounded(2, .bankers)
              print(r)    // -> 7.48

              So if you construct your decimal precisely, you get the result you expect.

              Share and Enjoy

              Quinn “The Eskimo!”
              Apple Developer Relations, Developer Technical Support, Core OS/Hardware
              let myEmail = "eskimo" + "1" + "@apple.com"