## Floor/Ceil able to handle decimal places (cf. Excel's Trunc function)

Get help with using AutoHotkey and its commands and hotkeys
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

### Floor/Ceil able to handle decimal places (cf. Excel's Trunc function)

[EDIT:] See this link for alternatives:
Ceil() with precision - AutoHotkey Community
https://autohotkey.com/boards/viewtopic.php?f=5&t=69935
One issue with the function below, is that if you ceil 2.22 to 2dp you get 2.23, this is because 2.22 is stored as 2.2200000000000002.
Although that is technically correct, if the function simply ceils the number presented to it, it may be more intuitive in such situations to lose some precision before rounding, as is done in functions in the link. I.e. if we see '2.2200000000000002', the user probably meant '2.22'.

- Round can round a number to n decimal places, or to the nearest ten/hundred/thousand etc.
- I was trying to create versions of Floor and Ceil that could do the same thing. I share them here because it's a little fiddly, in case anyone notices any problems or has any suggestions.
- An improved Floor function would be similar to Excel's Trunc function.

Code: Select all

``````q:: ;Round v. equivalent Floor/Ceil functions
MsgBox, % "1234.5678" "`r`n" JEE_Floor(1234.5678, 2) " " Round(1234.5678, 2) " " JEE_Ceil(1234.5678, 2)
MsgBox, % "1234.5" "`r`n" JEE_Floor(1234.5, 2) " " Round(1234.5, 2) " " JEE_Ceil(1234.5, 2)
MsgBox, % "1234" "`r`n" JEE_Floor(1234, 2) " " Round(1234, 2) " " JEE_Ceil(1234, 2)
MsgBox, % "1234.5678" "`r`n" JEE_Floor(1234.5678, 0) " " Round(1234.5678, 0) " " JEE_Ceil(1234.5678, 0)
MsgBox, % "1234.5678" "`r`n" JEE_Floor(1234.5678, -2) " " Round(1234.5678, -2) " " JEE_Ceil(1234.5678, -2)
return

;==================================================

;e.g. vDP:2 round down to 2 decimal places
;e.g. vDP:-2 round down to nearest 100

JEE_Floor(vNum, vDP:=0)
{
if !vDP
return Floor(vNum)
else if (vDP > 0)
return Format("{:0." vDP "f}", Floor(vNum * (10**vDP)) * (10**-vDP))
else ;if (vDP < 0)
return Floor(Floor(vNum * (10**vDP)) * (10**-vDP))
}

;==================================================

JEE_Ceil(vNum, vDP:=0)
{
if !vDP
return Ceil(vNum)
else if (vDP > 0)
return Format("{:0." vDP "f}", Ceil(vNum * (10**vDP)) * (10**-vDP))
else ;if (vDP < 0)
return Ceil(Ceil(vNum * (10**vDP)) * (10**-vDP))
}

;==================================================
``````
[EDIT:] Fixed typo. Before: > 1 and < 1. After: > 0 and < 0.

[EDIT:] A possible concern could be to program the functions in such a way that the maximum level of accuracy is preserved. Possibly, although I would probably do this as separate functions, you could write functions that treat the number as a string, and so an infinite level of accuracy is possible.
Last edited by jeeswg on 24 Nov 2019, 08:57, edited 3 times in total.
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

### Re: Floor/Ceil able to handle decimal places (cf. Excel's Trunc function)

One potential use for this would be in displaying disk drive capacities, which should normally be rounded down.

Code: Select all

``````;[JEE_Floor function]
;Floor/Ceil able to handle decimal places (cf. Excel's Trunc function) - AutoHotkey Community
;https://autohotkey.com/boards/viewtopic.php?f=5&t=41539

q:: ;friendly display file size
vList := "bytes,KB,MB,GB,TB"
vList2 := "0,1,1023,1024," ((1024**2)-1) "," (1024**2) "," ((1024**3)-1) "," (1024**3)
Loop Parse, vList2, % ","
{
vNum := A_LoopField
Loop Parse, vList, % ","
{
vUnit := A_LoopField
if (vNum = 1) && (A_Index = 1)
vUnit := "byte"
if (A_Index = 1)
vNum2 := vNum
else
vNum2 := JEE_Floor(vNum/(1024**(A_Index-1)), 2)
if (vNum2 < 1024)
break
}
MsgBox, % vNum2 " " vUnit
}
return
``````
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA