## Define function for rounding to precision

### Ryan Allan (view profile)

on 14 Aug 2019
Latest activity Edited by John D'Errico

### John D'Errico (view profile)

on 14 Aug 2019
Hi,
Rather than use the fix, floor, ciel functions, I’m trying to create a function to round a number up to a prescribed decimal place.
Eg.
Function roundup_value = ROUNDUP(value, decimalPlaces)
Any help would be greatly appreciated.

### Tags

on 14 Aug 2019

Usual scenario would be to multiply by 10^decimalPlaces, ceil and then divide by 10^decimalPlaces I would imagine.
e.g.
ceil( 1.23456789 * 10^4 ) / 10^4
You could probably use
doc round
with the second argument too, although if you want to enforce always rounding up it likely isn't worth it. I don't know why equivalent versions of ceil and floor don't exist. It was added relatively recently to round rather than in the original implementation, but I would have thought all that family of functions should have been updated the same way.

John D'Errico

### John D'Errico (view profile)

on 14 Aug 2019
Adam makes a good point, in that if round was extended as it was, then why did ceil and floor not get the same treatment? My guess is for the same reason I never thought to look to see if ceil and floor had the new capability. It is just something I've never had the slightest desire to do. Yes, I'll suppose a round to n digits has been at times useful, though I think it has been more when I answer a question about exactly that. Personally, I tend not to use it at all.
So why not? Why do I rarely ever use the capability to round a number to tenths, hundreths, etc? I tend not to do so, because I know that it is a fallacy in double precision floating point arithmetic to trust that a number is exactly rounded/truncated/ceiled to the nearest 0.1, or almost any fraction of an integer. (I do trust that Adam knows all this.)
format long g
X = rand(1,3)
X =
0.925425280986515 0.00558112226984153 0.186388406230158
Y = floor(X*10)/10
Y =
0.9 0 0.1
But are they exactly 0.9. 0, and 0.1? Only in the second case are they so.
sprintf('%0.55f',Y(1))
ans =
'0.9000000000000000222044604925031308084726333618164062500'
sprintf('%0.55f',Y(2))
ans =
'0.0000000000000000000000000000000000000000000000000000000'
sprintf('%0.55f',Y(3))
ans =
'0.1000000000000000055511151231257827021181583404541015625'
You can round/ceil/floor a number exactly to a fraction that is a pure power of 2 though. So to round/ceil/floor to the nearest multiple of 1/8, thus a pure power of 2, even though it is a negative power of 2?
Y8 = floor(X*8)/8
Y8 =
0.875 0 0.125
sprintf('%0.55f',Y8(1))
ans =
'0.8750000000000000000000000000000000000000000000000000000'
We can see it is stored as exactly 0.875 too, using my num2bin utility.
num2bin(Y8(1))
ans =
struct with fields:
Class: 'double'
Sign: 1
Exponent: -1
Mantissa: '11100000000000000000000000000000000000000000000000000'
BinaryExpansion: [-1 -2 -3]
BiSci: '1.1100000000000000000000000000000000000000000000000000 B-1'
BiCimal: '0.11100000000000000000000000000000000000000000000000000'
So Y8(1) is EXACTLY represented internally as 1/2 + 1/4 + 1/8 = 0.875.
So, while I accept that floor and ceil arguably should have been extended as was done to round, most of the time, you really are not getting what you asked for anyway.