Round value the float value in iOS - iphone

I am developing an app and want to round off values
i.e if the output is 4.8 I want to display 4.8
while if the output is 4.0 , I want to display 4
Also, it would be great if I could precisely round values : as in if value is 4.34 then round to 4.3 while if its 4.37 then round it to 4.4

One way to round floating point values is to just add 0.5 and then truncate the value.
double valueToRound = GetTheValueFromSomewhere();
double roundedValue = (double)((int)(valueToRound + 0.5));
This will round 1.4 down to 1.0 and 1.5 up to 2.0 for example. To round to other decimal places as you mentioned, simply multiply the initial value by 10, or 100, etc. use the same sort of code, and then divide the result by the same number and you'll get the same result at whatever decimal place you want.
Here's an example for rounding at an arbitrary precision.
double valueToRound = GetTheValueFromSomewhere();
int decimalPrecisionAtWhichToRound = 0;
double scale = 10^decimalPrecisionAtWhichToRound;
double tmp = valueToRound * scale;
tmp = (double)((int)(tmp + 0.5));
double roundedValue = tmp / scale;
So, if decimalPrecisionAtWhichToRound is set to 0 as in the above it'll round to the nearest whole integer. 1.4 will round to 1.0. 1.5 will round to 2.0.
If you set decimalPrecisionAtWhichToRound to 1, it would round to the nearest tenth. 1.45 would round to 1.5 and 1.43 would round to 1.4.

You need to first understand how to do rounding on paper, without someone showing you the code to do it. Write down some numbers and figure out how to round them.
To round to a specific decimal position you add half the value of that position and then truncate. Ie, 1.67 + 0.05 = 1.72 then truncate to 1.7.
But there are two tricky things in programming that aren't there when you do it on paper:
Knowing how to truncate -- There are several ways to do it while programming, but they're non-trivial.
Dealing with the fact that floating-point numbers are imprecise. Ie, there is no exact representation of, say, 1.7, but rather the two closest numbers are apt to be something like 1.69998 and 1.700001
For truncating the trick of multiplying the number by the appropriate power of 10 to produce an integer works pretty well. Eg, (1.67 + 0.05) * 10 = 17.2, then convert to int to get 17, then convert back to float and divide by 10 to get 1.7 (more or less). Or (if you're printing or displaying the value) just format the integer number with the decimal point inserted. (By formatting the integer value you don't have to deal with the problem of imprecise floating point representations.)
If you want to suppress trailing zeros it gets a bit trickier and you probably have to actually write some code -- format the number, then scan backwards and take off any trailing zeros up to the decimal point. (And take the decimal point too, if you wish.)

float number=17.125;
NSNumberFormatter *format = [[NSNumberFormatter alloc]init];
[format setNumberStyle:NSNumberFormatterDecimalStyle];
[format setRoundingMode:NSNumberFormatterRoundHalfUp];
[format setMaximumFractionDigits:2];
NSString *temp = [format stringFromNumber:[NSNumber numberWithFloat:number]];
NSLog(#"%#",temp);

double myNumber = 7.99;
NSString *formattedNumber = [NSString stringWithFormat:#"%.*f",
fmod(round(myNumber * 10), 10) ? 1 : 0, myNumber];

Related

Conversion from Float to CGFloat in Swift

I was converting Float => CGFloat and it gave me following result. Why It comes as "0.349999994039536" after conversion but works fine with Double => CGFloat?
let float: Float = 0.35
let cgFloat = CGFloat(float)
print(cgFloat)
// 0.349999994039536
let double: Double = 0.35
let cgFloat = CGFloat(double)
print(cgFloat)
// 0.35
Both converting “.35” to float and converting “.35” to double produce a value that differs from .35, because the floating-point formats use a binary base, so the exact mathematical value must be approximated using powers of two (negative powers of two in this case).
Because the float format uses fewer bits, its result is less precise and, in this case, less accurate. The float value is 0.3499999940395355224609375, and the double value is 0.34999999999999997779553950749686919152736663818359375.
I am not completely conversant with Swift, but I suspect the algorithm it is using to convert a CGFloat to decimal (with default options) is something like:
Produce a fixed number of decimal digits, with correct rounding from the actual value of the CGFloat to the number of digits, and then suppress any trailing zeroes. For example, if the exact mathematical value is 0.34999999999999997…, and the formatting uses 15 significant digits, the intermediate result is “0.350000000000000”, and then this is shorted to “0.35”.
The way this operates with float and double is:
When converted to double, .35 becomes 0.34999999999999997779553950749686919152736663818359375. When printed using the above methods, the result is “0.35”.
When converted to float, .35 becomes 0.3499999940395355224609375. When printed using the above method, the result is “0.349999994039536”.
Thus, both the float and double values differ from .35, but the formatting for printing does not use enough digits to show the deviation for the double value, while it does use enough digits to show the deviation for the float value.

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)

iPhone CorePlot proper formatting of y-axis

I am using CorePlot to graph a set of data. Data for my x-axis consists of dates, while data for my y-axis consists of floats (which I then turn into NSNumber). I am getting data from a feed, and the feed returns numbers with a large number of decimals, eg: 0.46673718852844, 4.59392222219, 353.1293012045.
I'm using the following piece of code to properly format y-axis:
NSNumberFormatter *numberFormatter = [[[NSNumberFormatter alloc] init] autorelease];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:3];
[numberFormatter setPositiveFormat:#"###0.000"];
CPTXYAxis *y = axisSet.yAxis;
y.labelingPolicy = CPTAxisLabelingPolicyAutomatic;
y.minorTicksPerInterval = 1;
y.preferredNumberOfMajorTicks = 5;
y.labelFormatter = numberFormatter;
In most cases, everything works fine. However, sometimes it displays the same value at multiple positions along the axis. See image below:
The values are presented correctly, I would just like to avoid unnecessary (0.466) labels. I've even tried to round the numbers to 3 decimals in numberForPlot method:
if(fieldEnum == CPTScatterPlotFieldY)
{
float floatNum = r.value;
floatNum *= 1000;
int intValue = (int) floatNum;
float decimal = floatNum - intValue;
if (decimal > 0.5) {
intValue++;
}
floatNum = intValue /1000.0;
return [NSNumber numberWithFloat:floatNum];
}
but there is no difference in labels.
The preferredNumberOfMajorTicks property tells the labeling algorithm how many tick marks to use. If you want three ticks, set it to 3. You could also increase the maximum number of fraction digits for the number formatter to avoid the rounding issue altogether.
I believe that because you have said that you want 5 major ticks, that is what you are going to get, regardless of how close the y axis values are. If you sense that the values are too close together, you will probably have to adjust your preferredNumberOfMajorTicks property.
In my app that I am using Core Plot, I turned off the automatic axis labeling and I am putting together my own x and y axis labels. It is a bit more work, but i like the flexibility of doing it myself.
What I did here was dynamically set my preferredNumberOfMajorTicks property while the graph is plotted. Since my formatter shows 3 decimal places, I used the following code to change the number of ticks depending on the Y axis range so that the formatter will show a unique value on the axis at each tick. Too many ticks means the decimal places get cut off and there are duplicate values on the Y axis.
CPTXYAxis *y = axisSet.yAxis;
{
y.preferredNumberOfMajorTicks = round([newYRange.length floatValue]/0.001);
}
I hope this helps.

Round a float to 3dp?

How do I round a float to three decimal places?
I have this:
(round(1000.0f * currentHue) / 1000.0f)
Which rounds it to 3 decimal places but leaves a bunch of 0s on the end.
Most numbers can't be represented precisely with floating point. If you need precision that bad pick appropriate scientific library. If you want to print it nicely, use formatters -
NSLog(#"%.3f", currentHue);
This is a fairly hairy way to do it... But it should work.
float x = [[NSString stringWithFormat:#"%1.3f",(round(1000.0f * currentHue) / 1000.0f)] floatValue];

Increment UISlider by .1 in range -1.0 to 1.0

I have found multiple ways to set a sliders value based on ints but I need to increment according to a float .1.
float value = [_xSlider value] *.1;
[_xSlider setValue: value/.1];
But I get a large float number not just 0.3.
I found the answer.
I needed to put the number of decimal places I wanted in front of the decimal then act like it was an int, then push the numbers back onto the other side of the decimal.
int value = [_xSlider value] * 10;
[_xSlider setValue: value * .1];