truncatingRemainder(dividingBy: ) returning nonZero remainder even if number is completely divisible - swift4

I am trying to get remainder using swift's truncatingRemainder(dividingBy:) method.
But I am getting a non zero remainder even if value I am using is completely divisible by deviser. I have tried number of solutions available here but none worked.
P.S. values I am using are Double (Tried Float also).
Here is my code.
let price = 0.5
let tick = 0.05
let remainder = price.truncatingRemainder(dividingBy: tick)
if remainder != 0 {
return "Price should be in multiple of tick"
}
I am getting 0.049999999999999975 as remainder which is clearly not the expected result.

As usual (see https://floating-point-gui.de), this is caused by the way numbers are stored in a computer.
According to the docs, this is what we expect
let price = //
let tick = //
let r = price.truncatingRemainder(dividingBy: tick)
let q = (price/tick).rounded(.towardZero)
tick*q+r == price // should be true
In the case where it looks to your eye as if tick evenly divides price, everything depends on the inner storage system. For example, if price is 0.4 and tick is 0.04, then r is vanishingly close to zero (as you expect) and the last statement is true.
But when price is 0.5 and tick is 0.05, there is a tiny discrepancy due to the way the numbers are stored, and we end up with this odd situation where r, instead of being vanishingly close to zero, is vanishing close to tick! And of course the last statement is then false.
You'll just have to compensate in your code. Clearly the remainder cannot be the divisor, so if the remainder is vanishingly close to the divisor (within some epsilon), you'll just have to disregard it and call it zero.
You could file a bug on this but I doubt that much can be done about it.
Okay, I put in a query about this and got back that it behaves as intended, as I suspected. The reply (from Stephen Canon) was:
That's the correct behavior. 0.05 is a Double with the value 0.05000000000000000277555756156289135105907917022705078125. Dividing 0.5 by that value in exact arithmetic gives 9 with a remainder of 0.04999999999999997501998194593397784046828746795654296875, which is exactly the result you're seeing.
The only rounding error that occurs in your example is in the division price/tick, which rounds up to 10 before your .rounded(.towardZero) has a chance to take effect. We'll add an API to let you do something like price.divided(by: tick, rounding: .towardZero) at some point, which will eliminate this rounding, but the behavior of truncatingRemainder is precisely as intended.
You really want to have either a decimal type (also on the list of things to do) or to scale the problem by a power of ten so that your divisor become exact:
1> let price = 50.0
price: Double = 50
2> let tick = 5.0
tick: Double = 5
3> let r = price.truncatingRemainder(dividingBy: tick)
r: Double = 0

Related

Returning exact change in SWIFT

I'm struggling with making sense of how to return the changeDue for my assignment. Trying to revise my incorrect code for class in prep for intro to programming final.
all I am trying to do is: create a method called quarters(). When I pass any double value (ChangeDue) into the method, I want to know precisely how many quarters there are as well as the partial quarter change returned.
Original code:
func getChange(Quarters: Double) -> Double {
var Change = Quarters
return Change;
}
var Quarters = 0.72;
var ChangeDue = getChange(Quarters / .25);
print(ChangeDue)
Slightly revised code which I seem to have made worse:
class changeDue {
var = quarters(.72)
func changeDue(Quarters: Double) {
var Change = Quarters
changeDue = changeDue - (quarters*.25)
}
var ChangeDue = getChange(int / .25);
print(changeDue)
}
notes/Feedback:
create a method called quarters(). When I pass any double value (ChangeDue) into the method, I want to know precisely how many quarters there are as well as the partial quarter change returned.
Create a class level variable, changeDue. This is where you will set your test input e.g. .78, 2.15.
In your method, calculate the number of quarters as the integer of changeDue/.25
Print the number of quarters.
Now you need the revised change after quarters are removed. changeDue=changeDue - (quarters*.25)
quarters = the integer of changedue/.25
changeDue is now = to the previous changeDue - (quarters times .25)
quarters(.72)
the integer of .72/.25 = 2
changedue=.72-(2 x .25) or .72 - .50 =.12
Print changeDue.
Any help would be appreciated. I've been working on this for longer than I want to admit.
Hint 1: Do not work with Double or fractional amounts. Turn dollars into pennies by multiplying everything by 100 before you start. Now you can do everything with integer arithmetic. After you get the answer, you can always divide by 100 to turn it back into dollars, if desired.
Hint 2: Do you know about the % operator? It tells you the remainder after a division.
I don't want to write your code for you (it's you who are being tested, not me, after all), but I'll just demonstrate with a different example:
51 / 7 is 7, because integer division throws away the remainder.
Sure, 7x7 is 49, with something left over. But what?
Answer: 51 % 7 is 2. Do you see?

Using two integers for ProgressBar

I can't figure this math out.
I have two numbers, lets say 1/11. I need to put this in a ProgressBar which means 100% is 1.0.
What I have now is this:
floatNum = Float(completedNum)!/Float(totalNum)!*100.0/10.0
This works fine for anything above 10%. Anything below 10%, lets say 9%, it will give me 90%.
You can simply divide completedNum by totalNum:
let progress = Float(completedNum) / Float(totalNum)
Assuming that
0 <= completedNum <= totalNum
the result will always be in range 0.0 ... 1.0

Accountant rounding in swift

I'm not aware how to round numbers in the following manner in Swift:
6.51,6.52,6.53, 6.54 should be rounded down to 6.50
6.56, 6.57, 6.58, 6.59 should be rounded down to 6.55
I have already tried
func roundDown(number: Double, toNearest: Double) -> Double {
return floor(number / toNearest) * toNearest
}
to no success. Any thoughts ?
Here's your problem (and it has nothing to do with Swift whatsoever): Floating point arithmetic is not exact. Let's say you try to divide 6.55 by 0.05 and expect a result of 131.0. In reality, 6.55 is "some number close to 6.55" and 0.05 is "some number close to 0.05", so the result that you get is "some number close to 131.0". That result is likely just a tiny little bit smaller than 131.0, maybe 130.999999999999 and floor () returns 130.0.
What you do: You decide what is the smallest number that you still want to round up. For example, you'd want 130.999999999999 to give a result of 131.0. You'd probably want 130.9999 to give a result of 131.0. So change your code to
floor (number * 20.0 + 0.0001);
This will round 6.549998 to 6.55, so check if you are Ok with that. Also, floor () works in an unexpected way for negative input, so -6.57 would be rounded down to -6.60, which is likely not what you want.

Rounding Off Decimal Value to Pevious and Next Hundreds

I am working in C#. I have decimal variable startFilter that contains value say 66.76. Now I want this decimal value to appear in the seach filter $0 to $100. But what I also want is, that the search filter starts from the first decimal value that comes in startFilter variable. So for instance in this case the search filter will start from $0 to $100 because the value in startFilter variable is 66.76, but in another case it can be $100 to $200 if the first value that comes in searchFilter is say $105.
Having said that, how should I round off the value in seachFilter to previous hundreds and the next hundreds. Like if the value is 66.76 it rounds off to 0 as floor and 100 as ceiling, so on and so forth.
Any idea how to do that in C#?
double value = ...
int rounded = ((int) Math.Round(value / 100.0)) * 100;
divide your original number by 100. get floor and celing values. Multiply each of them by 100.

Inaccurate division of doubles (Visual C++ 2008)

I have some code to convert a time value returned from QueryPerformanceCounter to a double value in milliseconds, as this is more convenient to count with.
The function looks like this:
double timeGetExactTime() {
LARGE_INTEGER timerPerformanceCounter, timerPerformanceFrequency;
QueryPerformanceCounter(&timerPerformanceCounter);
if (QueryPerformanceFrequency(&timerPerformanceFrequency)) {
return (double)timerPerformanceCounter.QuadPart / (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
}
return 0.0;
}
The problem I'm having recently (I don't think I had this problem before, and no changes have been made to the code) is that the result is not very accurate. The result does not contain any decimals, but it is even less accurate than 1 millisecond.
When I enter the expression in the debugger, the result is as accurate as I would expect.
I understand that a double cannot hold the accuracy of a 64-bit integer, but at this time, the PerformanceCounter only required 46 bits (and a double should be able to store 52 bits without loss)
Furthermore it seems odd that the debugger would use a different format to do the division.
Here are some results I got. The program was compiled in Debug mode, Floating Point mode in C++ options was set to the default ( Precise (/fp:precise) )
timerPerformanceCounter.QuadPart: 30270310439445
timerPerformanceFrequency.QuadPart: 14318180
double perfCounter = (double)timerPerformanceCounter.QuadPart;
30270310439445.000
double perfFrequency = (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
14318.179687500000
double result = perfCounter / perfFrequency;
2114117248.0000000
return (double)timerPerformanceCounter.QuadPart / (((double)timerPerformanceFrequency.QuadPart) / 1000.0);
2114117248.0000000
Result with same expression in debugger:
2114117188.0396111
Result of perfTimerCount / perfTimerFreq in debugger:
2114117234.1810646
Result of 30270310439445 / 14318180 in calculator:
2114117188.0396111796331656677036
Does anyone know why the accuracy is different in the debugger's Watch compared to the result in my program?
Update: I tried deducting 30270310439445 from timerPerformanceCounter.QuadPart before doing the conversion and division, and it does appear to be accurate in all cases now.
Maybe the reason why I'm only seeing this behavior now might be because my computer's uptime is now 16 days, so the value is larger than I'm used to?
So it does appear to be a division accuracy issue with large numbers, but that still doesn't explain why the division was still correct in the Watch window.
Does it use a higher-precision type than double for it's results?
Adion,
If you don't mind the performance hit, cast your QuadPart numbers to decimal instead of double before performing the division. Then cast the resulting number back to double.
You are correct about the size of the numbers. It throws off the accuracy of the floating point calculations.
For more about this than you probably ever wanted to know, see:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
http://docs.sun.com/source/806-3568/ncg_goldberg.html
Thanks, using decimal would probably be a solution too.
For now I've taken a slightly different approach, which also works well, at least as long as my program doesn't run longer than a week or so without restarting.
I just remember the performance counter of when my program started, and subtract this from the current counter before converting to double and doing the division.
I'm not sure which solution would be fastest, I guess I'd have to benchmark that first.
bool perfTimerInitialized = false;
double timerPerformanceFrequencyDbl;
LARGE_INTEGER timerPerformanceFrequency;
LARGE_INTEGER timerPerformanceCounterStart;
double timeGetExactTime()
{
if (!perfTimerInitialized) {
QueryPerformanceFrequency(&timerPerformanceFrequency);
timerPerformanceFrequencyDbl = ((double)timerPerformanceFrequency.QuadPart) / 1000.0;
QueryPerformanceCounter(&timerPerformanceCounterStart);
perfTimerInitialized = true;
}
LARGE_INTEGER timerPerformanceCounter;
if (QueryPerformanceCounter(&timerPerformanceCounter)) {
timerPerformanceCounter.QuadPart -= timerPerformanceCounterStart.QuadPart;
return ((double)timerPerformanceCounter.QuadPart) / timerPerformanceFrequencyDbl;
}
return (double)timeGetTime();
}