Splunk: 端数処理 - 切り上げ、切り下げ、切り捨て、四捨五入

しばしば必要となるのでメモ。

###### 実施環境： Splunk Free 8.2.2

###### 基本

 Splunk で数値の端数処理を行いたい場合は、 eval コマンドの関数を用いると実現できます。
四捨五入の場合は round 、切り上げの場合は ceiling 、切り下げの場合は floor を使用します。

```Splunk:Splunk
| makeresults
| eval NUM = 1.23
| eval NUM_R = round(NUM),
       NUM_H = ceiling(NUM),
       NUM_L = floor(NUM)
```

![スクリーンショット 2021-12-19 14.58.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/f66c87f2-d561-046c-9383-980c4734efac.png "1.23")

```Splunk:Splunk
| makeresults
| eval NUM = 4.50
| eval NUM_R = round(NUM),
       NUM_H = ceiling(NUM),
       NUM_L = floor(NUM)
```

![スクリーンショット 2021-12-19 15.09.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/13172183-f1e6-1755-5237-3137285ea7ec.png "4.50")

###### 負の数の場合

ただし、数値が負の数の場合は少々注意が必要です。
まず、端数が.0から.4の場合は、

* 切り上げは「値が大きくなる方 = 0に近づく方」
* 切り下げは「値が小さくなる方 = 0から遠ざかる方」
* 四捨五入は「絶対値が小さくなる方 = 0に近づく方」

になります。
特に切り下げについては、「端数を無視する(切り捨て)」とは異なることに注意してください。

```Splunk:Splunk
| makeresults
| eval NUM = -1.23
| eval NUM_R = round(NUM),
       NUM_H = ceiling(NUM),
       NUM_L = floor(NUM)
```

![スクリーンショット 2021-12-19 15.10.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/7113a38d-6f80-7817-aa57-ce82ddb915ab.png "-1.23")

さらに面倒なのが端数が.5から.9の場合です。
切り上げ、切り下げは端数が.0から.4の時と同様です。
ですが、四捨五入については、

* 端数が**.5ちょうど**の場合は「絶対値が小さくなる方 = 0に近づく方」
* 端数が**.5よりごくわずかでも大きい**場合は「絶対値が大きくなる方 = 0から遠ざかる方」

と、正の数の時とは異なる挙動を見せます。

```Splunk:Splunk
| makeresults
| eval NUM = -4.5
| eval NUM_R = round(NUM),
       NUM_H = ceiling(NUM),
       NUM_L = floor(NUM)
```

![スクリーンショット 2021-12-19 15.12.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/91a6fa31-a657-8ce5-c8d3-764c0c266d2b.png "-4.5")

```Splunk:Splunk
| makeresults
| eval NUM = -4.51
| eval NUM_R = round(NUM),
       NUM_H = ceiling(NUM),
       NUM_L = floor(NUM)
```

![スクリーンショット 2021-12-19 15.13.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/33d323a9-bb69-5570-4b48-4a7ee0d10226.png "-4.51")

なお、このように.5以下の値は捨て、.5より大きい値は拾う端数処理の方法を五捨五超入と呼びます。
本頁では round 関数が行う処理を便宜上四捨五入と呼んでいますが、厳密にはこのように四捨五入とは異なる処理なのです。

###### 切り捨て

 Splunk において、「切り捨て」を行う関数は存在しません。
正の数であれば「切り捨て」は「切り下げ」と同じなので floor 関数を使用すれば問題ありませんが、負の数も考える場合は if 関数などを併用して上手く分岐を行う必要があります。

```Splunk:Splunk
| makeresults count=5
| streamstats count AS NUM
| eval NUM = (NUM - 3) * 1.3
| eval NUM_T = if(NUM >= 0, floor(NUM), ceiling(NUM))
```

![スクリーンショット 2022-01-04 16.16.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/f63461b6-00da-72aa-9e5e-231d46e9eade.png "if")

###### -0

負の数を切り上げた際、値が0になる場合は0ではなく「-0」という表記になります。
数値としては通常の0と同値として扱われますし、計算にも問題なく使用できます。
ただし、文字列として扱う場合は「0」と「-0」は異なる値として扱われるので注意してください。

```Splunk:Splunk
| makeresults count=5
| streamstats count AS NUM
| eval NUM = (NUM - 3) * 0.4
| eval NUM_H = ceiling(NUM)
| eval NUM_H_CHK_I = if(NUM_H = 0, "ZERO", null()),
       NUM_H_CHK_S = if(NUM_H = "0", "ZERO", null())
```

![スクリーンショット 2022-01-04 16.28.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/b38486d6-b5a4-cc5f-54df-dbc60453962b.png "-0")

どうしても気になる場合は、0を足したりすれば0に揃います。

```Splunk:Splunk
| makeresults count=5
| streamstats count AS NUM
| eval NUM = (NUM - 3) * 0.4
| eval NUM_H = ceiling(NUM)
| eval NUM_H_PLUS_0 = NUM_H + 0
```

![スクリーンショット 2022-01-04 16.30.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/c0b47b21-a491-766d-680e-6de5b1ff9605.png "-0+0")

なお、四捨五入においては「-0」は発生しません。

```Splunk:Splunk
| makeresults count=5
| streamstats count AS NUM
| eval NUM = (NUM - 3) * 0.4
| eval NUM_R = round(NUM)
```

![スクリーンショット 2022-01-04 16.32.10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/30fe2fe6-14c2-fb69-98dc-442dedbdd707.png "0")

###### 端数処理を行う桁

 round 関数は第二引数で、四捨五入を行う桁を指定できます。
整数値にするなら0を指定し、小数点以下第1位までの値にするなら1を指定します。
では10単位の値にするなら-1なのかとなりますが、 round 関数の第二引数に負の数は指定できません。

```Splunk:Splunk
| makeresults
| eval NUM = 12.39
| eval NUM_R0  = round(NUM,  0),
       NUM_R1  = round(NUM,  1),
       NUM_R-1 = round(NUM, -1)
```

![スクリーンショット 2021-12-19 15.17.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/0e3ca9c9-c7ec-9696-8fef-f1b93c732247.png "round")

10や100単位の値に四捨五入したい場合は、一旦10や100で割ったものを四捨五入し、再度10や100を掛けて桁数を戻すといった処理を行うことで実現できます。
また、整数以外に切り上げ、切り下げしたい場合も、 ceiling 関数や floor 関数は第二引数を指定できないため、同様の処理が必要です。

```Splunk:Splunk
| makeresults
| eval NUM = 12.39
| eval NUM_R = round(NUM / 10) * 10,
       NUM_H = ceiling(NUM / 10) * 10,
       NUM_L = floor(NUM / 10) * 10
```

![スクリーンショット 2021-12-19 15.19.32.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1465018/dc9bbd8a-ed5c-a935-0634-b15e54466d11.png "10")