Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NSRoundBankers is not working as documented by Apple

So, according to Apple's documentation about NSRoundBankers:

Round to the closest possible return value; when halfway between two possibilities, return the possibility whose last digit is even.

While this is true for positive numbers, I am not getting the expected behaviour on negative numbers. Here is the piece of code I executed on the device and on the simulator, both printing the exact same results:

NSDecimalNumber *increment = [NSDecimalNumber decimalNumberWithMantissa:5 exponent:-2 isNegative:NO];
NSDecimalNumber *number = [NSDecimalNumber decimalNumberWithMantissa:10 exponent:-1 isNegative:YES];
NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundBankers scale:1 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:YES];
while ([number compare:@1] == NSOrderedAscending)
{
    NSLog(@";%@;%@", number, [number decimalNumberByRoundingAccordingToBehavior:handler]);
    number = [number decimalNumberByAdding:increment];
}

On negative numbers, it's not returning the one whose last digit is even, it basically rounds down.

For example, for -0.85 i should be getting -0.8, but I am getting -0.9

Am I doing something wrong?

Left table shows the ACTUAL behaviour, in red marked the wrong rounded values.

Right table shows the EXPECTED behaviour, in green the correct rounded values.

iOS Java

like image 302
lupidan Avatar asked Nov 10 '22 08:11

lupidan


1 Answers

Stumbled upon this today and it's probably a bug in Foundation. If the source code of swift-corelibs-foundation has anything to do with the actual Foundation code, I might have found the culprit: https://github.com/apple/swift-corelibs-foundation/blob/70f8af962ff182c78a81673e75fe725b5b1b7827/Foundation/Decimal.swift#L1970.

I believe 1 should be subtracted from remainder on the line 1970, not added to it. Rationale: if remainder is 5, what does adding 1 to it actually change? The case falls trough (line 1972) and the check on line 1974 succeeds either way, be it 5 or 6. If it were to become 4 for after subtracting, it will prevent adding 1 to self (line 1979) and keep the number even.

UPD the issue has been reported to Apple: FB7565793.

UPD 2 the issue has been fixed by Apple in the first betas of iOS 14 / macOS 11.0.

like image 172
Nikolay Kasyanov Avatar answered Nov 14 '22 21:11

Nikolay Kasyanov