Rounding a number up to a Ceiling

In this lesson we will see how to write a custom function that gives the ceiling of a number.

You can download the stack for this lesson here: https://tinyurl.com/y7ebh6ez

Update Note: In LiveCode 7.1 onwards, LiveCode has its own built-in "ceiling()" function. As such, the following lesson applies only to LiveCode versions earlier than 7.1.

Our custom function

We are going to write the function

ceiling(pNumber)

The function returns the ceiling of the given parameter pNumber. The ceiling of a number is the smallest following integer, more precisely ceiling(x) is the smallest integer not less than x.

The function will be called with a statement such as one of the following.

put ceiling(it) into field "Total Price"
if ceiling(field "Incident") > 4 then go next card

Our example stack

Our example stack

For this lesson all we need is an entry field and a button to call the ceiling function and return the result.

The ceiling function

The first thing the custom function must do is check that it has been passed a number, if the pNumber parameter passed to the function is not a number the function will return an error message.

The function's purpose is to produce the next higher number, or to "round up". We can't use the round function for this, because the round function rounds to the nearest integer, not necessarily to the next higher

e.g. round(2.4) is 2, rather than 3

However, if we truncate the number(to get its integer part) and then add 1, we do get the desired result. By truncating 2.4 we get 2, add 1 and we get 3, the desired result.

Are we done? Not quite: there are two cases where this formula does not produce the ceiling number.

1 - If the number is already an integer, it is its own ceiling, so we don't want to add 1 to it.

2 - if the number is negative and not an integer, the above doesn't give us the ceiling. For example, the ceiling of -3.6 is -3, but truncating -3.6 gives -3, adding 1 gives us -2.

In both these cases the truncating gives us the ceiling of the number, without having to add 1.

The trunc function

Luckily for us LiveCode has a built in trunc function which returns the integer part of a number so we can use it in our custom function.

Examples:

trunc(33.567) -- returns 33

trunc(-6.3) -- returns -6

The script of the ceiling function

The script of the ceiling function
function ceiling pNumber
	## Check we have been passed a number
	if pNumber is not a number then
		return "Error: not a number"
	end if
   
	## Check if the number is already an integer or is negative
	if pNumber < zero or pNumber is an integer then
		## truncating gives the ceiling
		return trunc(pNumber)
	else
		## truncate the number and add 1 to get the ceiling
		return trunc(pNumber) + 1
	end if
end ceiling

11 Comments

Marilyn Warren

Can you tell me how I can format a field so that it only has 2 decimal places?

Thank You

Hanson Schmidt-Cornelius

Hi Marilyn,

you can format values for a field by using the "format" function. You can find further information on this in the LiveCode Dictionary.

Kind Regards,

Hanson

Marilyn Warren

Could not find in dictionary as I was looking for "number", or "decimal", or "round".

Now that you pointed out "format" I was able to find in dictionary, BUT still unable to get it to work.

Where do I put this line of code?

set the numberFormat of field "Miles" to "0.00"

I tried to put the code in the field "Miles" script but it didn't seem to work, and not sure what handler I should use.

I also tried this line of code in the card script within the preOpen Card handler but this did not work either.

Thank you

Marilyn Warren

Another problem I am having, is after I have deployed my app to my android, for some reason, when I try to key in my number the keyboard keeps reverting back to the alphabet. So, in order to key in 8568 I would have to:

press numbers then 8
press numbers then 5
press numbers then 6
press numbers then 8

In other apps on my android, when I press numbers, the keyboard stays on numbers until I change it by toggling back to alpha.

How can I tell the app keyboard that the field is "numeric" and to stay on the numbers (until I toggle back to alpha)?

Thank You

Hanson Schmidt-Cornelius

Hi Marilyn,

it really depends on how you want to process the field data.
You can implement code that waits until the user has entered the data and then process the content entered, or you can test the data entered each time the user selects an entry.

Try something like this in the field script, if you want the field to test for each input event that occurs:

on textChanged
local tFieldData
local tCursorLoc
put the word 4 of the selectedChunk into tCursorLoc
put me into tFieldData
filter tFieldData with "[0-9]*" & "." & "[0-9]*"
if tFieldData is empty then
answer "Only input floating point numbers"
else
put the format ("%1.2f",me) into me
select after char tCursorLoc of me
end if
end textChanged

You will have to tweak the code to what you need and will probably want to replace the dialog box bit with something that removes unwanted characters.

With regards to the numbers keyboard, have a look at the following dictionary entry:
mobileSetKeyboardType

Kind Regards,

Hanson

Marilyn Warren

I tried your example code above and it did absolutely nothing. I tweeked it changed it - everything, but still my field came out with several decimal points. (I didn't even get an error message).

Perhaps if I explain what I am doing? It is so very simple, the answer shouldn't be so complex.

I have a button called "calculate" When I click on calculate, the "answer" appears in the "answer" field.

I would like the "answer" field to round off the answer to only show 2 decimal points.

So, what handler do I use, what script do I put it in, and what is the code?

Please help because I just can not figure this one out!

Also, the code:

mobileSetKeyboardType "numeric"

sounds great, but again, what handler do I use and what script do I put it in?

I tried putting it in the preOpen Card because all the entry fields are numeric, but that didn't work.

Thank You

Hanson Schmidt-Cornelius

Hi Marilyn,

the reason the code did not work is probably because it was not placed in the field script. You can put a breakpoint in the code and see if you hit the breakpoint when executing the code in the IDE. If you do not hit the breakpoint, then the code is not being executed.

Anyway, that should not matter anymore, your project does not require that code. All you have to do is use the following line:

put the format ("%1.2f", myResult) into myResult

"myResult" is the variable that holds the value your calculation produces. You must execute that line and then place the result into the filed in which it is to be displayed:

put myResult into field "answer"

"answer" is the name of the filed that is to receive the value.

The two lines here can go into the handler that processes the button click. This is probably a mouseUp handler.

The command for setting the keyboard type should be called before the keyboard is launched. Apart from that it does not matter from where it is called. For testing purposes on a device, you can add an "answer" dialog after a particular command/function, to see that it was called.
For example write the code:

mobileSetKeyboardType "numeric"
answer "Keyboard set to numeric" with "Okay"

Once you know that the dialog pops up, you also know that the keyboard setting has changed to numeric. Later remove or comment out the "answer" line, as you then know that mobileSetKeyboardType "numeric" was called.

Kind Regards,

Hanson

Tony Vazquez

I would think that your line of code

set the numberFormat of field "Miles" to "0.00"

or even

set the numberFormat of me to "0.00"

would work in the script of the field "Miles", perhaps triggered by a closefield handler.

Elanor Buchanan

The numberFormat is not a field property so cannot be used in this case.

An example of how to achieve the desired result would be

on mouseUp
put avg(1.1,1.2,1.3,1.4,1.5,1.6,) into tAvg
put format("%1.2f", tAvg) into field 1
end mouseUp

I hope that helps.

Kind regards

Elanor

Trevix

Is there an easy way to round a time ("hh:mm") to nearest half an hour?

Elanor Buchanan

Hi Trevix

Here are a couple of options, one is more succinct but perhaps more opaque.

function getFormattedTime pTime
local tHour,tMin, tFormattedTime

set the itemDel to ":"
put item 1 of pTime into tHour
put item 2 of pTime into tMin

if tMin < 15 then
put "00" into tMin
else if tMin > 15 and tMin < 45 then
put "30" into tMin
else
add 1 to tHour
put format("%02s",tHour) into tHour
put "00" into tMin
end if
return tHour & ":" & tMin
end getFormattedTime

function getFormattedTime pTime
local tMinutes
set the itemDelimiter to ":"
put item 1 of pTime * 60 + item 2 of pTime into tMinutes
put ((tMinutes + 15) div 30) * 30 into tMinutes
return format("%02d:%02d", tMinutes div 60, tMinutes mod 60)
end getFormattedTime

Elanor

Add your comment

This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.