github.com/siglens/siglens@v0.0.0-20240328180423-f7ce9ae441ed/pkg/utils/eventsFormatutils.go (about) 1 /* 2 Copyright 2023. 3 4 Licensed under the Apache License, Version 2.0 (the "License"); 5 you may not use this file except in compliance with the License. 6 You may obtain a copy of the License at 7 8 http://www.apache.org/licenses/LICENSE-2.0 9 10 Unless required by applicable law or agreed to in writing, software 11 distributed under the License is distributed on an "AS IS" BASIS, 12 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 See the License for the specific language governing permissions and 14 limitations under the License. 15 */ 16 17 package utils 18 19 import ( 20 "math" 21 "strconv" 22 "strings" 23 ) 24 25 // format the numbers to string 26 func roundPrec(x float64, prec int) float64 { 27 if math.IsNaN(x) || math.IsInf(x, 0) { 28 return x 29 } 30 31 sign := 1.0 32 if x < 0 { 33 sign = -1 34 x *= -1 35 } 36 37 var rounder float64 38 pow := math.Pow(10, float64(prec)) 39 intermed := x * pow 40 _, frac := math.Modf(intermed) 41 42 if frac >= 0.5 { 43 rounder = math.Ceil(intermed) 44 } else { 45 rounder = math.Floor(intermed) 46 } 47 48 return rounder / pow * sign 49 } 50 51 func numberFormat(number float64, decimals int, decPoint, thousandsSep string) string { 52 if math.IsNaN(number) || math.IsInf(number, 0) { 53 number = 0 54 } 55 56 var ret string 57 var negative bool 58 59 if number < 0 { 60 number *= -1 61 negative = true 62 } 63 64 d, fract := math.Modf(number) 65 66 if decimals <= 0 { 67 fract = 0 68 } else { 69 pow := math.Pow(10, float64(decimals)) 70 fract = roundPrec(fract*pow, 0) 71 } 72 73 if thousandsSep == "" { 74 ret = strconv.FormatFloat(d, 'f', 0, 64) 75 } else if d >= 1 { 76 var x float64 77 for d >= 1 { 78 d, x = math.Modf(d / 1000) 79 x = x * 1000 80 ret = strconv.FormatFloat(x, 'f', 0, 64) + ret 81 if d >= 1 { 82 ret = thousandsSep + ret 83 } 84 } 85 } else { 86 ret = "0" 87 } 88 89 fracts := strconv.FormatFloat(fract, 'f', 0, 64) 90 91 // "0" pad left 92 for i := len(fracts); i < decimals; i++ { 93 fracts = "0" + fracts 94 } 95 96 ret += decPoint + fracts 97 98 if negative { 99 ret = "-" + ret 100 } 101 return ret 102 } 103 104 func roundInt(input float64) int { 105 var result float64 106 107 if input < 0 { 108 result = math.Ceil(input - 0.5) 109 } else { 110 result = math.Floor(input + 0.5) 111 } 112 113 // only interested in integer, ignore fractional 114 i, _ := math.Modf(result) 115 116 return int(i) 117 } 118 119 func formatNumber(input float64) string { 120 x := roundInt(input) 121 xFormatted := numberFormat(float64(x), 2, ".", ",") 122 return xFormatted 123 } 124 125 func NearestThousandFormat(num float64) string { 126 127 if math.Abs(num) < 1000 { 128 xNum := formatNumber(num) 129 xNumStr := xNum[:len(xNum)-3] 130 return string(xNumStr) 131 } 132 133 xNum := formatNumber(num) 134 // first, remove the .00 then convert to slice 135 xNumStr := xNum[:len(xNum)-3] 136 xNumCleaned := strings.Replace(xNumStr, ",", " ", -1) 137 xNumSlice := strings.Fields(xNumCleaned) 138 count := len(xNumSlice) - 2 139 unit := [4]string{" K", " Million", " Billion", " Trillion"} 140 xPart := unit[count] 141 142 afterDecimal := "" 143 if xNumSlice[1][0] != 0 { 144 afterDecimal = string(xNumSlice[1][0]) 145 } 146 final := xNumSlice[0] + afterDecimal + xPart 147 return final 148 }