5

How do I store exact values for numbers in Firestore from the Objective-C SDK?

For instance, if I manually create an "abv" field with a value of "15.9", it shows that exact value.

enter image description here

However, if I update a value in Firestore from the Objective-C API with an NSNumber value of @(15.9), I get this approximate value in my Firestore document.

enter image description here

NSDictionary *data = @{@"abv": @(15.9)};
[documentReference updateData:data completion:^(NSError * _Nullable error) {

}];

Here's another example. I attempted to store the value 61.99 from my Objective-C app. I can manually edit the amount back to 61.99 from the web console. I do not understand why I can manually input exact decimal values from the web console but not from the Objective-C API.

enter image description here enter image description here

Berry Blue
  • 15,330
  • 18
  • 62
  • 113
  • I think you need strings as you seem to want to retain user input as is. – skaak Nov 05 '20 at 15:02
  • When you get that field from Firestore and print it in console on the iOS device, does it still print `15.89999...` or does it print the correct `15.9`? – trndjc Nov 05 '20 at 15:42
  • Firestore is going to reflect back exactly what you put in it. It doesn't in any way change the input data. It's likely the case that your app is adding this specific value, even if it's not what you expressed in your code. – Doug Stevenson Nov 05 '20 at 15:46
  • @DougStevenson Firestore will return exactly what was put in it but the web-based admin may not *render* 64-bit integers correctly (just as it appears on screen) despite them being correctly stored in the database. This could just be a rendering issue. – trndjc Nov 05 '20 at 16:04
  • Thanks for the comments but Firestore can store `15.9` exactly as a number. I just don't know how to send this exactly from the Objective-C SDK. If I send it as a string it gets stored as a string and if I send it as a number I get the imprecision. – Berry Blue Nov 05 '20 at 18:00
  • @bsod Yes, Firestore returns exactly as `(double)15.9` in the manual entry example. – Berry Blue Nov 05 '20 at 18:00

2 Answers2

2

This is a known issue with numerical accuracy of floats and well documented. You could handle the number before writing it into firestore i.e. keep the input as a string write it into firestore and handle the number afterwards. This Blog goes into some detail about it and I think will handle your case better or as @skaak says keep as a string write the value into firestore and handle using the method depicted in the blog.

Cleanbeans
  • 655
  • 4
  • 12
1

This solved the issue by using NSDecimalNumber. I can store numbers exactly now with two decimal precision.

NSNumber *number = (NSNumber *)value;
NSString *text = [NSString stringWithFormat:@"%.2f", number.doubleValue];
NSDecimalNumber *decimalNumber = [[NSDecimalNumber alloc] initWithString:text];
return decimalNumber;
Berry Blue
  • 15,330
  • 18
  • 62
  • 113