2

I am trying to recreate a calculator for my application. It looks like recreating a bicycle but it's my first project and I didn't expect that there is so much challenge. The last one is floating point error. I know that it is common problem but I can't see the way how I can resolve it in calculator.

Obviously that calculators can work good. I tried to find some prototype and most of them have same problem or more than this one.

To show result on the screen I'm using interpolation from double and it gives a result for example of adding 0.1 to 0.2 as 0.2999999... or multiplying 0.3 to 3 as 0.8999999999...

Rounding is inappropriate because we've never know how many useful digit we have after decimal.

How to represent this calculation to user similar as native calculator, for example: I need 0.1 + 0.2 = 0.3 and simultaneously 1 / 3 = 0.33333333

Below just example of calculation and my interpolation to string to show the result:

struct air: View {
    
    @State var data: String = "0" // creating var for showing
    @State var firstNumber: Double = 0.3 // exact number which I have problem could be 0.3, 0.6
    @State var secondNumber: Double = 3 // could be 3, 9, 12
    @State var result: Double = 0 // result of calculation
    
    
    var body: some View {
        VStack{
            Button("Push"){ // Initiating calculation
                result = calculate(first: firstNumber, second: secondNumber)
                data = String(result)
            }.frame(width: 80, height: 40)
                .background(Color.gray)
                .foregroundColor(.white)
            Text("result: Double = \(result)") // can see that result as Double is correct
                .font(.title)
            Text("data: String = \(data)") // can see that result as interpolated to String is incorrect and shows number with 9 in period
                .font(.title)
        }
    }
}
func calculate(first: Double, second:Double) -> Double {
    return first * second
}
Yukhnenko
  • 23
  • 2

1 Answers1

1

Since you want to operate in decimal, use the Decimal type rather than Double (which operates in binary, and so rounds in binary).

After changing all references from Double to Decimal, you will also likely need to use .formatted() to create Strings in some places. Decimal has a small number of missing API hooks. For example:

data = result.formatted()

You can pass various options to .formatted if you want different formats. For example:

data = result.formatted(.number.precision(.fractionLength(2))))

See also, Is floating point math broken?

Rob Napier
  • 286,113
  • 34
  • 456
  • 610