Round a float to 3dp? - iphone

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];

Related

Converting code from using doubles to BigDecimal

I've been writing a CAD type program for fun in JAVA. The other day I wrote some code to define a line which was tangent to 2 circles. I've been checking my numbers with a commercial CAD program and they have been fairly close. Usually to the 9th decimal point. My results really only need to be stored in an array to 7 decimal points. After successfully defining the line tangent to the 2 circles, I decided to test it and define a point which was the intersection of the line and one of the circles.
In one case I got the result I was looking for, in another case I got no intersection. After looking at a few of the calculations I realized I was getting a very very small variation of maybe 9 or ten decimal places. I'm thinking of rewriting the code using BigDecimal.
This is a small snippet of some of the code I need to rewrite. Once I started it became much more cumbersome than I was wanting to do. I'm thinking about just converting the results using BigDecimal and using the original code unless there is an easy way to convert the following code to a BigDecimal type of format.
private float[] offsetLine(float lnx1, float lny1, float lnz1, float lnx2, float lny2, float lnz2, String direction, float offset) {
double deltax = Math.abs(lnx2 - lnx1);
double deltay = Math.abs(lny2 - lny1);
double lineLength = Math.sqrt(deltax * deltax + deltay * deltay);
double stepx = (offset * deltay) / lineLength;
double stepy = (offset * deltax) / lineLength;
Ok I'll answer my own question. Here's some code I dug up. I could only round to 6 decimal places to get the rounding I wanted. Once I did my calculations in double values I called the subroutine roundDbl
double checkRadius1 = Math.sqrt(((cir1x - offsetpts[0])*(cir1x - offsetpts[0])) + ((cir1y - offsetpts[1]) * (cir1y - offsetpts[1])));
double checkRadiusRounded = roundDbl(checkRadius1, 6); //round to 6 decimal places
public static Float roundDbl(Double dblValue, int decimalPlace) {
String tempDblString = Double.toString(dblValue);
String tempDbl = new BigDecimal(tempDblString).setScale(decimalPlace, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
return Float.valueOf(tempDbl);
}

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)

Pack two floats within range into one float

In HLSL, how would I go about packing two floats within the range of 0-1 into one float with an optimal precision. This would be incredibly useful to compress my GBuffer further.
//Packing
float a = 0.45;
float b = 0.55;
uint aScaled = a * 0xFFFF;
uint bScaled = b * 0xFFFF;
uint abPacked = (aScaled << 16) | (bScaled & 0xFFFF);
float finalFloat = asfloat(abPacked);
//Unpacking
float inputFloat = finalFloat;
uint uintInput = asuint(inputFloat);
float aUnpacked = (uintInput >> 16) / 65535.0f;
float bUnpacked = (uintInput & 0xFFFF) / 65535.0f;
Converting floating point numbers to fixed point integers is an error prone idea, due to floats covering much larger magnitudes. Say unpacking sRGB will give you pow(255,2.2) values, which are larger than 0xffff, and you will need several times than amount for robust HDR. Generally fixed point code is very fragile, obfuscated and a nightmare to debug. People invented floats for a good reason.
There are several 16-bit float formats. IEEE 16-bit float one is optimized for numbers between -1.0 to 1.0, but also support numbers up to 0x10000, just in case you need HDR, still so you will need to normalize your larger floats for it, Then there is bfloat16, which behaves like normal 32-bit float, just with less precision. IEEE 16-bit floats are widely supported by modern CPUs and GPUs, and can also be converted quickly even in software. bfloat16 is just gaining popularity, so you will have to research if it is suitable for your needs. Finally you can introduce your own 16-bit float format, using integer log function, which is provided by most CPUs as a single instruction.

Round value the float value in iOS

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];