# How to floor or ceil a fixed point number?

Say I have a signed 64.64 fixed point number `18444899399302180000` or `0.9999` in floating point notation. How can I define a `floor` and `ceil` function that floors or ceils an `int128` signed 64.64 fixed point number?

``````function floor(int128) returns(int128);
function ceil(int128) returns(int128);

floor(18444899399302180000) == 0 // floor(0.9999) == 0
floor(-18444899399302180000) == 0 // floor(-0.9999) == -1

ceil(18444899399302180000) == 18446744073709551616 // ceil(0.9999) == 1
ceil(-18444899399302180000) == 0 // ceil(-0.9999) == 0
``````

Btw I'm using ABDKMath64x64 for working with signed 64.64 fixed point numbers.

• If you were using PRBMath instead, you would get floor and ceil function by default. Jan 21 at 9:27
• Sorry for the shameless plug but PRBMath is quickly becoming the industry's favorite math library. It's faster, more practical and more intuitive than ABDK. Jan 21 at 9:31
• @PaulRazvanBerg great suggestion, I'm loving it so far! Jan 21 at 16:02

I managed to implement both `floor` and `ceil` as follows. The `ABDKMath64x64.toInt` function essentially floors the signed fixed point number to a signed integer, hence the following would hold true:

• `toInt(-18444899399302180000) == -1` i.e. floor(-0.9999) == -1
• `toInt(0) == 0` i.e. floor(0) == 0
• `toInt(18444899399302180000) == 0` i.e. floor(0.9999) == 0
• `toInt(18446744073709551616) == 1` i.e. floor(1) == 1
• `toInt(-18446744073709551616) == -1` i.e. floor(-1) == -1

so all that is required is to then just cast the resulting integer result back to a signed fixed point number.

For `ceil` I first check if the signed fixed point number is a whole number integer by %(mod) by 1(unity), if it is then I simply return the number since the ceil of a whole number is that number. Else I take the fixed point number into the real number range above it's current real number range and then floor it, so for example if the number is `0.9999` I take it into the range of it's ceil i.e. [1, 2) by adding unity which makes it 1.9999, then flooring it gives us the ceil i.e. 1 in this case. hence the following holds true:

• `ceil(-18444899399302180000) == 0` i.e. ceil(-0.9999) == 0
• `ceil(0) == 0` i.e. ceil(0) == 0
• `ceil(18444899399302180000) == 0` i.e. ceil(0.9999) == 1
• `ceil(18446744073709551616) == 1` i.e. ceil(1) == 1
• `ceil(-18446744073709551616) == -1` i.e. ceil(-1) == -1
``````pragma solidity ^0.8.0;

import { ABDKMath64x64 } from "./ABDKMath64x64.sol";

contract FloorCeil {

int128 constant unity = 18446744073709551616;

function floor(int128 fp) public pure returns(int128) {
return ABDKMath64x64.fromInt(int256(ABDKMath64x64.toInt(fp)));
}

function ceil(int128 fp) public pure returns(int128) {
if (fp == 0 || fp%unity == 0) {
return fp;
}