Is it possible to simulate a floor() function with elementary arithmetic?

16.2k Views Asked by At

I'm using a "programming language" that only allows basic operations: addition, subtraction, multiplication, and division.

Is it possible to emulate a floor function (i.e. drop the decimals a number) by using only those operators? I'm only interested in positive numbers

Edit: Here's the documentation describing what's possible (which is only elementary arithmetic)

10

There are 10 best solutions below

16
On BEST ANSWER

Let $$f_1(x)=x+c_1$$ $$f_2(x)=x\cdot c_2$$ where $c_1,c_2$ are some constants, and $f_1$ represents addition and subtraction, and $f_2$ represents multiplication and division. Functions $f_1$ and $f_2$ have inverse function, but $\lfloor{x}\rfloor$ does not have an inverse function. So, if we assume it is possible to find $\lfloor{x}\rfloor$ from $x$ using $f_1$ and $f_2$, then it is possible to find $x$ from $\lfloor{x}\rfloor$. Contradiction.

2
On

The floor function has jump discontinuities.

A function obtained with elementary arithmetic is a rational function and those can only have pole (or infinite) discontinuities.

4
On

Yes it is possible, but depends on the available arithmetic and the rounding mode. With IEEE-double you can round a double $x$ to the nearest integer with this:

$c=2^{52};$

$x = x + c; \mathrm{round} = x - c$ for $x\ge 0\;$ and

$x = x - c; \mathrm{round} = x + c$ for $x<0.$

With the rounding to the next integer you can implement floor.

3
On

try modulo 1 : x=x-(x mod 1) It works with both + and - numbers.

4
On

I know I'm a little late to this party but thought it was worth noting that given a basic round function you can find the floor by doing round(x - .5)

4
On

If you can use a loop and extra variables, you can repeatedly subtract one until left with only the decimal part.

Something like:

floor(x):
floor = 0
While x >= 1
    floor += 1
    x -= 1
End While

Not the greatest, and will take a long time for large numbers, but it could be tweaked.

It also won't work for negative values, but that's easily fixed.

1
On

For overkill, if you also have sine you can use the Fourier expansion:

$$\lfloor x \rfloor = x- \frac{1}{2} + \frac{1}{\pi} \sum_{k=1}^{\infty} \frac{\sin 2 \pi k x}{k}$$

(except when $x$ is already an integer, I think). If you don't have sine you can build that up using a Taylor's series. Also $\pi$.

4
On

You can do integer division using complex arithmetic, but there's a different function for each divisor. For example,

$$\left\lfloor \frac{x}{2} \right\rfloor = \frac{x}{2} - \frac{1 - (-1)^x}{4} $$

for $x$ an integer. For higher $k$ you'll use $k$th roots of unity.

0
On

If you are able to use a javascript library as well as CSS (maybe not possible if you are using something like eBay) you can use http://lesscss.org/functions/ to extend your CSS to allow a floor function.

0
On

Programming languages typically use floating-point arithmetic defined by the IEEE 754 standard. Roughly speaking, if the exact result of an operation calculated using mathematical real arithmetic has an absolute value $2^k ≤ x < 2^{k+1}$, then x will be rounded to the nearest integer multiple of $2^{k-52}$. The exception is the case where x is exactly between the two nearest integer multiples of $2^{k-52}$, in which case x will be rounded to the even multiple.

If the absolute value x is between $2^{52} ≤ x < 2^{53}$, then x will be rounded to the nearest integer or the nearest even integer if x is exactly between two integers. Any floating-point numbers with an absolute value $x ≥ 2^{52}$ are actually integers. And any floating-point operation where the exact result is an integer with $-2^{53} ≤ x ≤ 2^{53}$ will give the exact result.

This gives a simple implementation: If the absolute value of x is $2^{52}$ or greater then x is an integer and floor (x) = x. Otherwise; first add then subtract $2^{52}$ from x if x >= 0, but first subtract then add $2^{52}$ to x if x < 0. This rounds x to one of the two nearest integers. If the result is greater than the original value of x, subtract 1.

I think this is quite close to the implementation that is typically used by current compilers.