1

I had core data storage, my field "expensesAmount" in Float identify. The value of expensesAmount is 6.3. But when I retrieve it to variable "expensesAmount" as below, it become 6.30000019. So my totalAmount is not correct.

Can someone help?

let entity:NSManagedObject = data?.object(at: i) as! NSManagedObject                    
if let expensesAmount = entity.value(forKey: "expensesAmount") as? Float {                         
   totalAmount += expensesAmount                   
}
thedp
  • 8,350
  • 16
  • 53
  • 95
user831098
  • 1,803
  • 6
  • 27
  • 47

2 Answers2

0

Try Follwoing :

let entity:NSManagedObject = data?.object(at: i) as! NSManagedObject

if let expensesAmount = entity.value(forKey: "expensesAmount") as? NSNumber {

totalAmount += expensesAmount.floatValue

}
Sandeep Kumar
  • 328
  • 1
  • 8
0

I think this is related to how the floating point numbers are expressed with IEEE-754 standard. With the standard, not all kinds of numbers with fraction may necessarily be expressed precisely even with double. This is irrelevant to Swift. The next small code in C will reproduce your issue.

int main(int argc, char **argv) {
  float fval = 6.3f;
  double dval = 6.3;
  printf("%.10f : %.17f\n", fval, dval);
  // 6.3000001907 : 6.29999999999999980
}

So, if you need the real accuracy in fractional part, you need to consider some other way.

EDITED: I checked with NSDecimalNumber and it's working as expected. Here is an example:

    let bval = NSDecimalNumber(string: "6.3")  // (1) 6.3
    let bval10 = bval.multiplying(by: 10.0)  // 63.0
    let dval = bval.doubleValue
    let dval10 = bval10.doubleValue
    print(String(format: "%.17f", dval))  // 6.29999999999999982
    print(String(format: "%.17f", dval10))  // (6) 63.00000000000000000
    let bval2 = NSDecimalNumber(mantissa: 63, exponent: -1, isNegative: false)
    print(bval2)  // 6.3
    let bval3 = NSDecimalNumber(mantissa: 123456789, exponent: -4, isNegative: true)
    print(bval3)  // -12345.6789

As you can see at (6), there's no round off when converting 6.3 at (1). Note 63.0 can be precisely expressed w/ float/double.

beshio
  • 794
  • 2
  • 7
  • 17
  • Any suggestion for this issues? I had to convert to double so the result look like 6.29999999999999980. As I use Charts 3.0, need to convert the value in Double – user831098 Nov 17 '16 at 08:15
  • Double may not always solve your issue. If you need the real accuracy in fractional part, you need to do integer arithmetic. To do so, you need to know number of fractional digits (0.XXX <=3), and multiply 1/XXX, so that all of the asthmatic is in integer. Or you need to check if BCD arthritic is available with iOS. – beshio Nov 17 '16 at 08:27
  • I checked Apple's document and it seems NSDecimalNumber can handle base-10 arithmetic (BCD). I don't have Mac with me now and I can't check but from the document, it seems to work. check https://developer.apple.com/reference/foundation/nsdecimalnumber – beshio Nov 17 '16 at 08:33