I have two variables, a speed and a minimum. The speed gets compared to the minimum to see if the speed should continue decreasing. For some reason, even when the speed is equal to the minimum, it continues to decrease the speed.
var wallSpeed : CGFloat!
var wallSpeedMin : CGFloat!
var wallSpeedChange : CGFloat!
override init(){
wallSpeed = 0.0035
wallSpeedMin = 0.0034
wallSpeedChange = 0.0001
}
The speed minimum is close to the speed for testing purposes.
if wallSpeed > wallSpeedMin
{
print("Wall speed has been increased")
wallSpeed = wallSpeed - wallSpeedChange
print("New speed is \(wallSpeed!)")
}else
{
print("Player moved up screen")
//Move player up instead
playerNode.position.y = playerNode.position.y + 5
print("Players Y value is \(playerNode.position.y)")
}
It never hits the else statement, even though the wall speed is equal to the wall speed minimum after the first decrease.
Do I have my if statement set up incorrectly? What is causing this behavior?
Floating point math does not work like you're expecting it to. Check Is floating point math broken?
You can't compare floating point numbers like this way...
Since the way of the floating point number represented we can't simply do some math on them....
when we use integers they are represented directly in binary format, and you can do any arithmetic calculation on them, while floating point numbers are 32 bits container following the IEEE 754 standard divided in three sections :
1 bit S for the sign
8 bits for the exponent
23 bits for the mantissa
For more information Comparing Floating Point Numbers and Floating Point in Swift
Related
I'm working on a program in which i want to store the distance the user walked since pressing a button. I retrieve the distance via geolocator package and display it on screen which works just fine.
I know there are some distanceBetween-Function for locations, but as far as i noticed, they are just calculating the distance between 2 points and not the actual distance the user walked (For example, if the user starts at one point X, walks over to Point Y and back to X would end in comparing start-and endpoint (X to X), which results in distance: 0, but i want the distance X -> Y -> X.
I added following function that calculated the distance based on longitude/latitude.
double distance(Position start, Position current){
return double.parse((acos(sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude))*6371).toStringAsFixed(2));
}
I call it every frame and store the distance between the current and last gps position.
Works slowly but fine, except one Problem:
Somewhen, the double suddenly turns into "NaN", and i can't figure out why.
It's completely random when this occurs - At the beginning, it was always around 0.6, but it also occurred around 4.5 and 0.2, so i think the problem may be somewhere else.
Can anybody help?
Or does anybody knows a built-in-function that can solve the same problem?
I tried parsing the double to only have 2 decimal spaces (Didn't round it before) because i thought the number might just got too many decimal spaces to be displayed, but error still occured.
I have a second task that is happening at the same time each time stamp, so i thought it was hindering retrieving the GPS, so i tried disabling it, but it didn't change anything.
It's possible that you are getting numerical stability issues with the spherical law of cosines since you're calculating the distance on every frame? It is known that the formula has conditioning issues for very small distances (less than one meter).
Note that the domain for
arccosine(x) is given by -1 <= x <= 1. If in your case you were to supply a value greater than 1 (or smaller than -1) you would get a NaN result.
If you are still debugging this you can add a simple print statement:
double distance(Position start, Position current){
double x = sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude);
if (x > 1 || x < -1) {
print("error");
}
return ((acos(sin(start.latitude)*sin(current.latitude)+cos(start.latitude)*cos(current.latitude)*cos(current.longitude-start.longitude))*6371));
}
If this is indeed the case, then you have a few options, use the Haversine formula because it is better conditioned for small distances, or simply set x to 1 if it's above 1. This anyway just means that the distance is zero.
For more information (and the Haversine formula) see also: Great circle distance
I really didn't think about the arccosines domain...
So i updated my code with your proposition to:
double distance(Position start, Position current) {
double x = sin(start.latitude) * sin(current.latitude) + cos(start.latitude) * cos(current.latitude) * cos(current.longitude - start.longitude);
if (x > 1 || x < -1) {
if (kDebugMode) {
print("error");
}
return 0;
}
return double.parse((acos(x) * 6371).toStringAsFixed(2));
}
It works fine, thank you for your help!
I was doing some work using the CoreBluetooth API and ran into a problem. All of the places I have looked, they say that to convert RSSI (Signal Strength of Bluetooth), you must do things like:
Distance = 10 ^ ((Measured Power – RSSI)/(10 * N))
And:
var txPower = -59 //hard coded power value. Usually ranges between -59 to -65
if (rssi == 0) {
return -1.0;
}
var ratio = rssi*1.0/txPower;
if (ratio < 1.0) {
return Math.pow(ratio,10);
}
else {
var distance = (0.89976)*Math.pow(ratio,7.7095) + 0.111;
return distance;
}
I have tried all of the above and everything I could find. None of it gets me the accurate measurements from about 0.5 meters to around 5 - 7 meters of distance between.
My code to do so is making both phones using the app as a central and peripheral Bluetooth and in my didDiscoverPeripheral callback from CentralManager, I get the RSSI - which I want to convert to a distance (meter, feet).
Along with that:
I also need to find out how to get the Measured Power (RSSI Strength at 1 meter) of iPhones as it would really help in the accurate calculations.
Also, what does environmental factor mean in terms of Bluetooth? What do the different environmental factors mean (which have the range of 2-4). Is there a way to change or increase the Broadcasting Power value of the Apple Device?
Basically, I am looking for an accurate RSSI to distance formula which works from distances from 0.5 meter to 5-7 meters
Thank you so much!
This is what is a common solution:
pow(10, ((-56-Double(rssi))/(10*2)))*3.2808
It was good for most distances but got very inaccurate as you get close or too far, so I ended up using bins kind of like Apple's iBeacons (Unknown, Far, Near, Immediate). If the raw RSSI is less than -80, then it is far, if it is more than -50, then it is immediate, and if it is between those two, it is near. This solution worked for me.
I try to find the steps between a min and a max value with a given step-size, using swift 2.1.
So we have a min and a max value, both of type Double. The step-size is a Double too. If min is 0.0 and max 0.5 with steps of 0.1, the result is 6, obviously.
But if I start with -0.1 as the minimum value, the result is 6 too. But should be 7, agree?
Here is my Playground example:
let min:Double = -0.1
let max:Double = 0.5
let step:Double = 0.1
var steps: Int {
return Int((max - min) / step) + 1
}
print("steps: \(steps)") // returns "steps: 6", but should be 7
The result is 6.99999999 if we use a Double for the steps variable. But this loss of precision only occurs when our min value is negative.
Do you know a workaround? I just don't want to round() each time I calculate with Doubles.
When you use Int() it forces truncation of your number, which always rounds towards zero. So, 6.9999 becomes 6 rather than 7, because it's closer to zero. If you use round() first it should help:
var steps: Int {
return Int(round((max - min) / step) + 1.0)
}
That's always not a good idea to calculate integral steps based on floating point ranges, you'll always encounter issues, and you won't be able to do much.
Instead I recommend to build your logic on integral steps, and calculate double values based on integral values (not vice versa as you do). I.e. you don't calculate integral step based on range, but you set your integral number of steps and calculate your double step.
I have a UISlider to give a range of a radius of search (for 5 - x miles, max x=100 miles), and I want to be able to get a random radius distance within this range.
#IBAction func sliderMoved(sender: UISlider){
//gives a range (minimum range 5 miles, maximum range 5 - 100 miles)
var range = (sender.value*95)+5
//gives a random distance in miles from within that range
var distance = Int((arc4random()%(range))+1)
}
When I try to assign "distance" I get the error "could not find an overload for '%' that accepts the supplied arguments".
Use arc4random_uniform()
let distance = arc4random_uniform(UInt32(range)) - 1
arc4random_uniform() will perform the modulo operation without bias.
The problem is that the sender.value is a UISlider.value that is a Float. arc4random is a UInt32 which is your main issue here.
What you've done is try to convert the whole thing to an Int when you just need the internal components to be matching first. So get the range and the arc4random to the same type (I've done a Float here) and then do the casting you want =
Int(Float(arc4random()) % range + 1)
You of course could also use arc4random_uniform as the other commenters have stated as in :
arc4random_uniform(UInt32(range)) + 1
which is actually much better if you don't really care about the value of your range (especially any decimal part).
http://www.raywenderlich.com/forums/viewtopic.php?f=2&t=20282
I'm really scratching my head here in an effort to understand a quote i read somewhere that says "the more we zoom inside the fractal, the more iteration we will most likely need to perform".
so far, i haven't been able to find any mathematical / academical paper that proves that saying.
i've also managed to find a small code that calculates the mandelbrot set, taken from here :
http://warp.povusers.org/Mandelbrot/
but yet, wasn't able to understand how zooming affects iterations.
double MinRe = -2.0;
double MaxRe = 1.0;
double MinIm = -1.2;
double MaxIm = MinIm+(MaxRe-MinRe)*ImageHeight/ImageWidth;
double Re_factor = (MaxRe-MinRe)/(ImageWidth-1);
double Im_factor = (MaxIm-MinIm)/(ImageHeight-1);
unsigned MaxIterations = 30;
for(unsigned y=0; y<ImageHeight; ++y)
{
double c_im = MaxIm - y*Im_factor;
for(unsigned x=0; x<ImageWidth; ++x)
{
double c_re = MinRe + x*Re_factor;
double Z_re = c_re, Z_im = c_im;
bool isInside = true;
for(unsigned n=0; n<MaxIterations; ++n)
{
double Z_re2 = Z_re*Z_re, Z_im2 = Z_im*Z_im;
if(Z_re2 + Z_im2 > 4)
{
isInside = false;
break;
}
Z_im = 2*Z_re*Z_im + c_im;
Z_re = Z_re2 - Z_im2 + c_re;
}
if(isInside) { putpixel(x, y); }
}
}
Thanks!
This is not a scientific answer but a one with common sense. In theory, to decide whether a point belongs to the Mandelbrot set or not, you should iterate infinitely, and check if the value ever reaches Infinity. This is practically useless so we make assumptions:
We iterate only 50 times
We check that iteration value ever gets larger than 2
When you zoom into a Mandelbrot set, the second assumption remains valid. However zooming means increasing the significant fractional digits of the point coordinates.
Say you start with (0.4,-0.2i).
Iterating over and over this value increases the digits used, but won't lose significant digits. Now when your point coordinate looks such: (0.00000000045233452235, -0.00000000000943452634626i) to check if that point is in the set you need much more iteration to see if that iteration would ever reach 2 not to mention that if you use some kind of Float type, you will lose significant digits at some zoom level and you'll have to switch to an arbitrary precision library.
Trying is your best friend :-) Calculate a set with a low iteration and a high iteration and subtract the second image from the first. You will always see change at the edges (where black pixels meet colored pixels), but if your zooming level is high (meaning: the point coordinates have a lot of fractional digits) you will get a different image.
You asked how zooming affects iterations and my typical zoom to iterations ratio is that if you zoom in to a 9th of the size I increase iterations by 1.7. A 9th of the size of course means that both width and height is divided by 3.
Making this more generic I actually use this in my code
Complex middle = << calculate from click in image >>
int zoomfactor = 3;
width = width / zoomfactor;
maxiter = (int)(maxiter * Math.Sqrt(zoomfactor));
minimum = new Complex(middle.Real - width, middle.Imaginary - width);
maximum = new Complex(middle.Real + width, middle.Imaginary + width);
I find that this relation between zoom and iterations works out pretty well, the details in the fractals still come well on deep zooms without getting too crazy on the iterations too fast.
How fast you want to zoom if your own preference, I like a zoomfactor of 3 but anything goes. The important thing is that you need to keep the relation between the zoomfactor and the increase in interations.