Swift: Double conversion inconsistency. How to correctly compare Doubles? - swift

I have a very simple function to convert temperature from ˚C TO ˚K.
func convertKelvinToCelsius(temp:Double) ->Double {
return temp - 273.15
}
And I have a unit test to drive this function. This is where the problem is:
func testKelvinToCelsius(){
var check1 = conv.convertKelvinToCelsius(200.00) // -73.149999999999977
var check2 = 200.00 - 273.15 // -73.149999999999977
var check3 = Double(-73.15) // -73.150000000000006
//Passes
XCTAssert(conv.convertKelvinToCelsius(200.00).description == Double(-73.15).description, "Shoud convert from celsius kelvin")
//Fails
XCTAssert(conv.convertKelvinToCelsius(200.00) == Double(-73.15), "Shoud convert from celsius kelvin")
}
When you add a breakpoint and check the values of check1, check2 and check3, they are very interesting:
check1 Double -73.149999999999977
check2 Double -73.149999999999977
check3 Double -73.150000000000006
Questions:
Why does Swift return different values for check1/check2 and check3
How can I get the second test to pass, because writing it like I did the test1 smells. Why should I have to convert Doubles to Strings to be able to compare them?
Finally, when I println check1, check2 and check3, they all print to be '-73.15'. Why? Why not print accurately, and not confuse the programmers!?
To Reproduce:
Just type 200 - 273.15 == -73.15 in you playground and watch it go false!!

This is expected behavior for floating point values. They cannot be 100% accurately represented.
You can use the XCTAssertEqualWithAccuracy function to assert floating point values are within a given range of each other.
The reason println prints the same value for all is because it internally rounds them to two decimals (I assume).

This is not a Swift specific issue, this is related to the fact how decimal numbers are created in computers and what is their precision. You will need to work with DBL_EPSILON.

Swift, like most languages, uses binary floating point numbers.
With binary floating point numbers, some numbers can be represented exactly, but most can't. What can be represented exactly are integers unless they are very large (for example, 100000000000000.0 is fine), and such integers multiplied or divided by powers of two (7.375 is fine, it is 59.0 / 8, but 7.3 isn't).
Every floating point operation gives you the exact result, rounded to the nearest floating-point number. So you get
200.0 -> Exactly 200
273.15 -> A number very close to 273.15
200 - 273.15 -> A number very close to -73.15
-73.15 -> A number very close to -73.15
If you compare two numbers that are both very very close to -73.15 they are not necessarily equal. That's not a problem of the == operator; that one will determine correctly whether they are equal or not. The problem is that the two numbers can actually be different.

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?

Multiplying two double value gives negative number in flutter

I need to multiply two large numbers for example,
double x = 318191400000;
double result =x*x;
But i am getting negative value for this when building in flutter .
Please help me on this.
[1]: https://i.stack.imgur.com/eyxJ4.png
You're not actually multiplying two doubles here, but two ints which is overflowing the 64-bit integer resulting in a negative number.
With doubles:
void main() {
double x = 318191400000;
print(x*x); // Result: 1.0124576703396e+23
}
With ints:
void main() {
int x = 318191400000;
print(x*x); // Result: -8411186631728820224
}
If you ever print a double to the console, you'll always see it displayed in either scientific notation (for extremely large or small values) or with a decimal point with at least one trailing digit.
Finally i have found solution and sharing here for anyone having these kind of issues,
xValues[index].toDouble() * yValues[index].toDouble()
This gives the expected result which is 1.0124576703396e+23

Using arc4random_uniform to return a both whole and non whole doubles

Using Swift, I am trying to figure out how to use arc4random_uniform to return a number like 37.7. The guidance I must abide by is I must do it in a function, the random double must be between 0 - 300. I have been able to build a function that randomly returns doubles between the range but can't find anything that will lead me to outputting random non whole numbers
//function to randomly generate a double number like 105.3
func makeRandDbl() -> Double {
let randGenerator: Double = Double(arc4random_uniform(301))
print(randGenerator)
return randGenerator
}
makeRandDb()
To generate a Double in the range 0.0 to 300.0 (with one digit following the decimal):
Double(arc4random_uniform(3001))/10.0
You can extend this to more decimal places. For two decimal places (0.00 to 300.00):
Double(arc4random_uniform(30001))/100.0
For three decimal places (0.000 to 300.000):
Double(arc4random_uniform(300001))/1000.0
This has the advantage of being able to actually generate whole values. In the first case 10% of the numbers will be whole. In the second case 1% of the numbers will be whole. And in the third, 0.1% of the numbers will be whole.
This is your function, I believe:
extension Double {
/// Generates a random `Double` within `0.0...1.0`
public static func random() -> Double {
return random(0.0...1.0)
}
/// Generates a random `Double` inside of the closed interval.
public static func random(interval: ClosedInterval<Double>) -> Double {
return interval.start + (interval.end - interval.start) * (Double(arc4random()) / Double(UInt32.max))
}
}
Usage example:
Double.random(0...300)
It is taken from RandomKit library - it looks very useful for various purposes.
One approach would be to convert the result of arc4random_uniform to double, divide the result by UInt32.max, and then multiply the result by 300.
let rand = 300 * Double(arc4random_uniform(UInt32.max)) / Double(UInt32.max)
This would produce a value between 0 and 300, inclusive. The number of possible values that you are going to get is UInt32.max.

Division returns something different in functions

Paste the following code into a playground:
5.0 / 100
func test(anything: Float) -> Float {
return anything / 100
}
test(5.0)
The first line should return 0.05 as expected. The function test returns 0.0500000007450581. Why?
It has nothing to do with functions. Your first example is using type Double which represents floating point numbers more precisely by using 64 bits. If you were to change your second example to:
func test(anything: Double) -> Double {
return anything / 100
}
test(5.0)
You would get the result you expect. Float uses only 32 bits of data, thus it provides a less precise representation of the number. Also, floating point numbers are stored as binary values and frequently are only an approximation of the base 10 representation. That is why 0.05 is showing up as 0.0500000007450581 when stored as a Float.

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();
}