webmcp
view framework/env/format/decimal.lua @ 243:d5cba50e16ae
Send "Connection: close" header to terminate process
author | jbe |
---|---|
date | Sun Mar 01 20:52:03 2015 +0100 (2015-03-01) |
parents | 9fdfb27f8e67 |
children |
line source
1 --[[--
2 text = -- text with the value formatted as decimal number
3 format.decimal(
4 value, -- a number, a fraction or nil
5 {
6 nil_as = nil_text, -- text to be returned for a nil value
7 digits = digits, -- digits before decimal point
8 precision = precision, -- digits after decimal point
9 decimal_shift = decimal_shift -- divide the value by 10^decimal_shift (setting true uses precision)
10 }
11 )
13 Formats a (floating point) number or a fraction as a decimal number. If a 'digits' option is set, the number of digits before the decimal point is increased up to the given count by preceding it with zeros. The digits after the decimal point are adjusted by the 'precision' parameter. The 'decimal_shift' parameter is useful, when fixed precision decimal numbers are stored as integers, as the given value will be divided by 10 to the power of the 'decimal_shift' value prior to formatting. Setting 'decimal_shift' to true will copy the value for 'precision'.
15 --]]--
17 function format.decimal(value, options)
18 -- TODO: more features
19 local options = options or {}
20 local special_chars = charset.get_data().special_chars
21 local f
22 if value == nil then
23 return options.nil_as or ""
24 elseif atom.has_type(value, atom.number) then
25 f = value
26 elseif atom.has_type(value, atom.fraction) then
27 f = value.float
28 else
29 error("Value passed to format.decimal(...) is neither a number nor a fraction nor nil.")
30 end
31 local digits = options.digits
32 local precision = options.precision or 0
33 local decimal_shift = options.decimal_shift or 0
34 if decimal_shift == true then
35 decimal_shift = precision
36 end
37 f = f / 10 ^ decimal_shift
38 local negative
39 local absolute
40 if f < 0 then
41 absolute = -f
42 negative = true
43 else
44 absolute = f
45 negative = false
46 end
47 absolute = absolute + 0.5 / 10 ^ precision
48 local int = math.floor(absolute)
49 if not atom.is_integer(int) then
50 if f > 0 then
51 return "+" .. special_chars.inf_sign
52 elseif f < 0 then
53 return minus_sign .. special_chars.inf_sign
54 else
55 return "NaN"
56 end
57 end
58 local int_str = tostring(int)
59 if digits then
60 while #int_str < digits do
61 int_str = "0" .. int_str
62 end
63 end
64 if precision > 0 then
65 local decimal_point =
66 options.decimal_point or
67 locale.get('decimal_point') or '.'
68 local frac_str = tostring(math.floor((absolute - int) * 10 ^ precision))
69 while #frac_str < precision do
70 frac_str = "0" .. frac_str
71 end
72 assert(#frac_str == precision, "Assertion failed in format.float(...).") -- should not happen
73 if negative then
74 return special_chars.minus_sign .. int_str .. decimal_point .. frac_str
75 elseif options.show_plus then
76 return "+" .. int_str .. decimal_point .. frac_str
77 else
78 return int_str .. decimal_point .. frac_str
79 end
80 else
81 if negative then
82 return special_chars.minus_sign .. int
83 elseif options.show_plus then
84 return "+" .. int_str
85 else
86 return int_str
87 end
88 end
89 end