Module:Convert: Difference between revisions

some overflow checks; fix ntsh to match Jimp's changes to Template:Ntsh in Sep 2012
(refactor and implement disp=table/tablecen)
(some overflow checks; fix ntsh to match Jimp's changes to Template:Ntsh in Sep 2012)
Line 3:
 
local MINUS = '−' -- Unicode U+2212 MINUS SIGN (UTF-8: e2 88 92)
local formatabs = stringmath.formatabs
local floor = math.floor
local format = string.format
local log10 = math.log10
 
Line 90 ⟶ 91:
cvt_bug_convert = { 'Bug: Cannot convert between specified units', 'general' },
cvt_empty_option = { 'Ignored empty option "%s"', 'option', warning = true },
cvt_invalid_num = { 'Number is too large or too small', 'general' },
cvt_mismatch = { 'Cannot convert "%s" to "%s"', 'mismatch' },
cvt_no_default = { 'Unit "%s" has no default output unit', 'unknown' },
Line 441 ⟶ 443:
end
 
local function ntsh_complementvalid_number(textnum)
-- Return texttrue (stringif ofnum digits)is aftera subtractingvalid each digit from 9number.
-- Expressed as a string, overflow or other problems are indicated with
local result = ''
-- text like "1.#INF" or ".#IND" which are regarded as invalid here.
local first, last = 1, #text
if type(num) == 'number' and tostring(num):find('#', 1, true) == nil then
while first <= last do
localreturn lenblock = last + 1 - firsttrue
if lenblock > 12 then
lenblock = 12
end
local block = tonumber(text:sub(first, first + lenblock - 1))
local nines = tonumber(string.rep('9', lenblock))
local fmt = '%0' .. tostring(lenblock) .. '.0f'
result = result .. format(fmt, nines - block)
first = first + lenblock
end
return result
end
 
local function ntsh(nnum, debug)
-- Return html text to be used for a hidden sort key so that
-- the given number will be sorted in numeric order.
-- If debug == 'yes', output is in a box (not hidden).
-- This implements Template:Ntsh (number table sorting, hidden).
local result, i, f, style
if nnot >= 0valid_number(num) then
if nnum >< 1e160 then
result = '~1000000000000000000'
else
i, fresult = math.modf(n)'9000000000000000000'
f = floor(1e6 * f)
result = format('&1%016.0f%06d', i, f)
end
elseif num == 0 then
result = '5000000000000000000'
else
nlocal mag = floor(log10(abs(num)) + 1e-n14)
iflocal n > 1e16 thenprefix
if num > 0 result = '!'then
lenblockprefix = 127000 + mag
else
i, fprefix = math.modf(n)2999 - mag
fnum = floor(1e6num *+ f10^(mag+1)
result = format('%016.0f%06d', i, f)
result = '&0' .. ntsh_complement(result)
end
result = format('%d', prefix) .. format('%015.0f', floor(num * 10^(14-mag)))
end
if debug == 'yes' then
Line 765 ⟶ 758:
numstr = change_sign(numstr)
end
if tostringnot valid_number(value):find('#', 1, true) then
return nil -- overflow or similar
end
Line 847 ⟶ 840:
end
singular = false -- any fraction (even with value 1) is regarded as plural
end
if not valid_number(value) then -- for example, "1e310"
return false, { 'cvt_invalid_num' }
end
if show == nil then
Line 874 ⟶ 870:
-- Return true, n where n = integer equivalent to given text,
-- or return false, t where t is an error message table.
-- Input should be the text for a simple integer (no separators, no Unicode minus).,
-- limited size). Using regex avoids irritations with input like '-0.000001'.
if text == nil then return false, { 'cvt_no_num' } end
if #text > 9 or text:match('^-?%d+$') == nil then
return false, { invalid, text }
end
Line 923 ⟶ 919:
return nil
end
return withspace(withspace(preunit1, 1), -1)
end
preunit2 = preunit2 or ''
Line 1,351 ⟶ 1,347:
-- Calculate minimum precision from absolute value.
adjust = 0
local kelvin = math.abs((invalue - in_current.offset) * in_current.scale)
if kelvin < 1e-8 then -- assume nonzero due to input or calculation precision problem
minprec = 2
Line 1,367 ⟶ 1,363:
adjust = -log10(in_current.scale)
else
adjust = log10(math.abs(invalue / outvalue))
end
adjust = adjust + log10(2)
Line 1,510 ⟶ 1,506:
inclean = extra.inclean or inclean
outvalue = extra.outvalue
end
if not valid_number(outvalue) then
return false, { 'cvt_invalid_num' }
end
local isnegative
Line 1,862 ⟶ 1,861:
end
if value then -- some unusual units do not always set value field
value = math.abs(value)
singular = (0 < value and value < 1.0001)
end
Anonymous user