Loss of precision when dividing doubles in swift - swift

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.

Related

How to round up and down double to the nearest interval in dart/flutter

I'm trying to round down/up for example i want to round down 134.78 with nearest 0.5 the output should be 134.5 and if i round up the output should be 135.0 I tried ((134.78 / 0.5).floorToDouble() * 0.5) but the result is 134.0 not 134.5
Multiply your number by two before any calculations.
Use the desired round feature. (Floor or Ceiling).
Divide the result by two again:
double a = 134.78;
print((2*a).floorToDouble()/2); // prints 134.5
print((2*a).ceilToDouble()/2);// prints 135
Which is the desired result.
You can read more here.

How would you round up or down a Float to nearest even numbered integer in Swift 3?

I need a little help rounding up or down a float to the nearest even number in Swift.
Eg:
32.86 would be closest to 32
33.86 would be closest to 34
If you want to round to the nearest even number, divide by 2, round and then multiply by 2:
let rounded = Int(round(value / 2.0)) * 2
What about this using Swift 4?
33.86.rounded(.toNearestOrEven)

How to floor a floating point number? from 0.999 to 0.99

I want to truncate any value that appears after two decimal places in Matlab/Octave.
I do not want the value 1. I instead want the value to be 0.99 after "rounding/flooring".
Please use only built-in functions to accomplish this task.
Scale up the number, apply rounding, scale the result down by the same value:
x = 0.999;
y = floor (100 * x) / 100;

Swift - arc4random() could not find an overload for '%' that accepts the supplied arguments

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

How to round off x-ticklabels to the nearest 50

I need to round off the X-ticklabels in an excel chart to the nearest 50. The charts are created in VBA, the data series is in a worksheet so I would be happy to use a solution in either. I have written the following function that rounds to the nearest 50:
Function RoundTo50(number As Double) As Double
RoundTo50 = WorksheetFunction.Round(number * 2, -2) / 2
End Function
I have applied it to the min and max x limits of the chart and it works for them, but I can't work out how to apply this to all the ticklabels in between. I thought of applying it to all the data before plotting but that would alter the plot which I don't want to do. I would prefer for the ticklabels to be slightly misaligned due the rounding.
Can you do this with a formatting string? Or any other way?
Thanks
So the answer is as follows (thanks to Sam Ward for the comment that pushed me in the right direction):
Use my RoundTo50() function to round of the min and max limits to the nearest 50. Calculate what the interval should be for a reasonable amount of grid lines, in my case 12. Round this interval to the nearest 50.
Function RoundTo50(number As Double) As Double
RoundTo50 = WorksheetFunction.Round(number * 2, -2) / 2
End Function
and
With Sheets("Report").ChartObjects.Add(...)
.Chart.Axes(xlCategory).MinimumScale = RoundTo50(Sheets(sheetName).Range("M4"))
.Chart.Axes(xlCategory).MaximumScale = RoundTo50(Sheets(sheetName).Range("M124"))
.Chart.Axes(xlCategory).MajorUnit = RoundTo50((.Chart.Axes(xlCategory).MaximumScale - .Chart.Axes(xlCategory).MinimumScale) / 12)
.Chart.Axes(xlCategory).MinorUnit = .Chart.Axes(xlCategory).MajorUnit / 3
I would still be very much interested in being able to do this with a formatting string though as I have a secondary axis in percent and the grid lines from rounding to 50 are slightly offset with the tick marks of the secondary axis. With a formatting string they would be perfectly aligned (because they would be slightly in the wrong place but I would prefer that).