2 Replies
      Latest reply on Aug 11, 2018 4:41 AM by luopengfei14
      Ilonka Buwalda Level 1 Level 1 (0 points)

        I wrote a string extension

         

        extension String {

            func formatDoubleToString(value: Double, places: Int) -> String {

                var result : String

                if places == 1 {

                    result = String(format: "%.1f", value)

                }

                else if places == 2 {

                    result = String(format: "%.2f", value)

                }

                else {

                    result = String(format: "%.f", value)

                }

                

                return result

            }

         

        All my test on this extension pass except these ones where I work with .999 :

        Display 99.99 with 1 decimal place 99.9

        Display 9999.999 with two decimal places 9999.99

         

            func testStringExtentionFormatDoubleToStringPlaces1_1(){

                let result: String = String().formatDoubleToString(value: 99.99, places: 1)

                XCTAssert(result == "99.9", "Display 99.99 with 1 decimal place 99.9")

            }

         

            func testStringExtentionFormatDoubleToStringZeroPlaces2_7(){

                let result: String = String().formatDoubleToString(value: 9999.999, places: 2)

                XCTAssert(result == "9999.99", "Display 9999.999 with two decimal places 9999.99")

            }

        • Re: Display 99.99 with 1 decimal place 99.9 Fail
          QuinceyMorris Level 8 Level 8 (5,680 points)

          You probably can't do it this way. String format specifiers (%f, etc) follow the IEEE printf formatting rules (pubs.opengroup.org/onlinepubs/009695399/functions/printf.html), and it says this about "%f":

           

          "The double argument shall be converted to decimal notation in the style "[-]ddd.ddd", where the number of digits after the radix character is equal to the precision specification. If the precision is missing, it shall be taken as 6; if the precision is explicitly zero and no '#' flag is present, no radix character shall appear. If a radix character appears, at least one digit appears before it. The low-order digit shall be rounded in an implementation-defined manner."

           

          I tried these in a playground:

           

          print (String(format: "%.1f", 99.99))
          print (String(format: "%.2f", 9999.999))
          

           

          and it prints:

           

          100.0
          10000.00
          

           

          Clearly, the "implementation-defined" rounding takes the requested precision into account. You can code around this if you want, but the result would be lying: 99.99 is a lot closer to 100.0 than it is to 99.9.

          • Re: Display 99.99 with 1 decimal place 99.9 Fail
            luopengfei14 Level 1 Level 1 (0 points)
            let number = 99.9999
            
            let ret1 = floor(number * 10) / 10 // 99.9
            
            let ret2 = floor(number * 100) / 100 // 99.99