한국   대만   중국   일본 
Mo đun:Math ? Wikipedia ti?ng Vi?t B??c t?i n?i dung

Mo đun : Math

Trang mô đun bị khóa vô hạn
Bach khoa toan th? m? Wikipedia
Tai li?u mo đun [ t?o ]
--[[


Mo đun nay cung c?p nhi?u phep toan c? b?n.


]]


local
 yesno
,
 getArgs
 -- lazily initialized


local
 p
 =
 {}
 -- Holds functions to be returned from #invoke, and functions to make available to other Lua modules.

local
 wrap
 =
 {}
 -- Holds wrapper functions that process arguments from #invoke. These act as intemediary between functions meant for #invoke and functions meant for Lua.


--[[

Helper functions used to avoid redundant code.

]]


local
 function
 err
(
msg
)

	-- Generates wikitext error messages.

	return
 mw
.
ustring
.
format
(
'<strong class="error">L?i đ?nh d?ng: %s</strong>'
,
 msg
)

end


local
 function
 unpackNumberArgs
(
args
)

	-- Returns an unpacked list of arguments specified with numerical keys.

	local
 ret
 =
 {}

	for
 k
,
 v
 in
 pairs
(
args
)
 do

		if
 type
(
k
)
 ==
 'number'
 then

			table.insert
(
ret
,
 v
)

		end

	end

	return
 unpack
(
ret
)

end


local
 function
 makeArgArray
(...)

	-- Makes an array of arguments from a list of arguments that might include nils.

	local
 args
 =
 {...}
 -- Table of arguments. It might contain nils or non-number values, so we can't use ipairs.

	local
 nums
 =
 {}
 -- Stores the numbers of valid numerical arguments.

	local
 ret
 =
 {}

	for
 k
,
 v
 in
 pairs
(
args
)
 do

		v
 =
 p
.
_cleanNumber
(
v
)

		if
 v
 then

			nums
[
#
nums
 +
 1
]
 =
 k

			args
[
k
]
 =
 v

		end

	end

	table.sort
(
nums
)

	for
 i
,
 num
 in
 ipairs
(
nums
)
 do

		ret
[
#
ret
 +
 1
]
 =
 args
[
num
]

	end

	return
 ret

end


local
 function
 fold
(
func
,
 ...)

	-- Use a function on all supplied arguments, and return the result. The function must accept two numbers as parameters,

	-- and must return a number as an output. This number is then supplied as input to the next function call.

	local
 vals
 =
 makeArgArray
(...)

	local
 count
 =
 #
vals
 -- The number of valid arguments

	if
 count
 ==
 0
 then
 return

		-- Exit if we have no valid args, otherwise removing the first arg would cause an error.

		nil
,
 0

	end

	local
 ret
 =
 table.remove
(
vals
,
 1
)

	for
 _
,
 val
 in
 ipairs
(
vals
)
 do

		ret
 =
 func
(
ret
,
 val
)

	end

	return
 ret
,
 count

end


--[[

Fold arguments by selectively choosing values (func should return when to choose the current "dominant" value).

]]

local
 function
 binary_fold
(
func
,
 ...)

	local
 value
 =
 fold
((
function
(
a
,
 b
)
 if
 func
(
a
,
 b
)
 then
 return
 a
 else
 return
 b
 end
 end
),
 ...)

	return
 value

end


--[[

random


T?o s? ng?u nhien.


Cach s? d?ng:

{{#g?i: Math | random }}

{{#g?i: Math | random | gia tr? t?i đa }}

{{#g?i: Math | random | gia tr? t?i thi?u | gia tr? t?i đa }}

]]


function
 wrap
.
random
(
args
)

	local
 first
 =
 p
.
_cleanNumber
(
args
[
1
])

	local
 second
 =
 p
.
_cleanNumber
(
args
[
2
])

	return
 p
.
_random
(
first
,
 second
)

end


function
 p
.
_random
(
first
,
 second
)

	math.randomseed
(
mw
.
site
.
stats
.
edits
 +
 mw
.
site
.
stats
.
pages
 +
 os.time
()
 +
 math.floor
(
os.clock
()
 *
 1000000000
))

	-- math.random will throw an error if given an explicit nil parameter, so we need to use if statements to check the params.

	if
 first
 and
 second
 then

		if
 first
 <=
 second
 then
 -- math.random doesn't allow the first number to be greater than the second.

			return
 math.random
(
first
,
 second
)

		end

	elseif
 first
 then

		return
 math.random
(
first
)

	else

		return
 math.random
()

	end

end


--[[

order


Xac đ?nh b?c đ? l?n c?a s?.


Cach s? d?ng:

{{#g?i: Math | order | gia tr? }}

]]


function
 wrap
.
order
(
args
)

	local
 input_string
 =
 (
args
[
1
]
 or
 args
.
x
 or
 '0'
);

	local
 input_number
 =
 p
.
_cleanNumber
(
input_string
);

	if
 input_number
 ==
 nil
 then

		return
 err
(
'gia tr? cho vao ham b?c đ? l?n khong ph?i la s?'
)

	else

		return
 p
.
_order
(
input_number
)

	end

end


function
 p
.
_order
(
x
)

	if
 x
 ==
 0
 then
 return
 0
 end

	return
 math.floor
(
math
.
log10
(
math.abs
(
x
)))

end


--[[

precision


Xac đ?nh đ? chinh xac c?a m?t s? b?ng cach s? d?ng bi?u di?n chu?i


Cach s? d?ng:

{{ #g?i: Math | precision | gia tr? }}

]]


function
 wrap
.
precision
(
args
)

	local
 input_string
 =
 (
args
[
1
]
 or
 args
.
x
 or
 '0'
);

	local
 trap_fraction
 =
 args
.
check_fraction
;

	local
 input_number
;


	if
 not
 yesno
 then

		yesno
 =
 require
(
'Mo đun:Yesno'
)

	end

	if
 yesno
(
trap_fraction
,
 true
)
 then
 -- Returns true for all input except nil, false, "no", "n", "0" and a few others. See [[Module:Yesno]].

		local
 pos
 =
 string.find
(
input_string
,
 '/'
,
 1
,
 true
);

		if
 pos
 ~=
 nil
 then

			if
 string.find
(
input_string
,
 '/'
,
 pos
 +
 1
,
 true
)
 ==
 nil
 then

				local
 denominator
 =
 string.sub
(
input_string
,
 pos
+
1
,
 -
1
);

				local
 denom_value
 =
 tonumber
(
denominator
);

				if
 denom_value
 ~=
 nil
 then

					return
 math
.
log10
(
denom_value
);

				end

			end

		end

	end


	input_number
,
 input_string
 =
 p
.
_cleanNumber
(
input_string
);

	if
 input_string
 ==
 nil
 then

		return
 err
(
'gia tr? cho vao ham đ? chinh xac khong ph?i la s?'
)

	else

		return
 p
.
_precision
(
input_string
)

	end

end


function
 p
.
_precision
(
x
)

	if
 type
(
x
)
 ==
 'number'
 then

		x
 =
 tostring
(
x
)

	end

	x
 =
 string.upper
(
x
)


	local
 decimal
 =
 x
:
find
(
'%.'
)

	local
 exponent_pos
 =
 x
:
find
(
'E'
)

	local
 result
 =
 0
;


	if
 exponent_pos
 ~=
 nil
 then

		local
 exponent
 =
 string.sub
(
x
,
 exponent_pos
 +
 1
)

		x
 =
 string.sub
(
x
,
 1
,
 exponent_pos
 -
 1
)

		result
 =
 result
 -
 tonumber
(
exponent
)

	end


	if
 decimal
 ~=
 nil
 then

		result
 =
 result
 +
 string.len
(
x
)
 -
 decimal

		return
 result

	end


	local
 pos
 =
 string.len
(
x
);

	while
 x
:
byte
(
pos
)
 ==
 string.byte
(
'0'
)
 do

		pos
 =
 pos
 -
 1

		result
 =
 result
 -
 1

		if
 pos
 <=
 0
 then

			return
 0

		end

	end


	return
 result

end



--[[

max


Tim ra đ?i s? t?i đa.


Cach s? d?ng:

{{#g?i:Math| max | gia tr? 1 | gia tr? 2 | … }}


L?u y: Cac gia tr? khong ph?i s? đ??c b? qua.

]]


function
 wrap
.
max
(
args
)

	return
 p
.
_max
(
unpackNumberArgs
(
args
))

end


function
 p
.
_max
(...)

	local
 max_value
 =
 binary_fold
((
function
(
a
,
 b
)
 return
 a
 >
 b
 end
),
 ...)

	if
 max_value
 then

		return
 max_value

	end

end


--[[

median


Tim trung v? c?a t?p h?p s?


Cach s? d?ng:

{{#invoke:Math | median | s? th? 1 | s? th? 2 | ...}}

HO?C

{{#invoke:Math | median }}

]]


function
 wrap
.
median
(
args
)

	return
 p
.
_median
(
unpackNumberArgs
(
args
))

end


function
 p
.
_median
(...)

	local
 vals
 =
 makeArgArray
(...)

	local
 count
 =
 #
vals

	table.sort
(
vals
)


	if
 count
 ==
 0
 then

		return
 0

	end


	if
 p
.
_mod
(
count
,
 2
)
 ==
 0
 then

		return
 (
vals
[
count
/
2
]
 +
 vals
[
count
/
2
+
1
])
/
2

	else

		return
 vals
[
math.ceil
(
count
/
2
)]

	end

end


--[[

min


Tim ra đ?i s? t?i thi?u.


Cach s? d?ng:

{{#g?i:Math| min | gia tr? 1 | gia tr? 2 | … }}

HO?C

{{#g?i:Math| min }}


N?u khong cho vao đ?i s? nao, no l?y cac gia tr? t? khung m?. L?u y r?ng cac gia

tr? khong ph?i s? đ??c b? qua.

]]


function
 wrap
.
min
(
args
)

	return
 p
.
_min
(
unpackNumberArgs
(
args
))

end


function
 p
.
_min
(...)

	local
 min_value
 =
 binary_fold
((
function
(
a
,
 b
)
 return
 a
 <
 b
 end
),
 ...)

	if
 min_value
 then

		return
 min_value

	end

end


--[[

sum


Tim t?ng


Cach s? d?ng:

{{#invoke:Math| sum | gia tr? 1 | gia tr? 2 | ... }}

HO?C

{{#invoke:Math| sum }}


L?u y, m?i gia tr? khong ph?i s? đ?u b? b? qua.

]]


function
 wrap
.
sum
(
args
)

	return
 p
.
_sum
(
unpackNumberArgs
(
args
))

end


function
 p
.
_sum
(...)

	local
 sums
,
 count
 =
 fold
((
function
(
a
,
 b
)
 return
 a
 +
 b
 end
),
 ...)

	if
 not
 sums
 then

		return
 0

	else

		return
 sums

	end

end


--[[

average


Tinh phep trung binh.


Cach s? d?ng:

{{#g?i:Math| average | gia tr? 1 | gia tr? 2 | … }}

HO?C

{{#g?i:Math| average }}


L?u y: Cac gia tr? khong ph?i s? đ??c b? qua.


]]


function
 wrap
.
average
(
args
)

	return
 p
.
_average
(
unpackNumberArgs
(
args
))

end


function
 p
.
_average
(...)

	local
 sum
,
 count
 =
 fold
((
function
(
a
,
 b
)
 return
 a
 +
 b
 end
),
 ...)

	if
 not
 sum
 then

		return
 0

	else

		return
 sum
 /
 count

	end

end


--[[

round


Lam tron s? theo đ? chinh xac đ??c đ?nh ro.


Cach s? d?ng:

{{#g?i:Math | round | gia tr? | đ? chinh xac }}


--]]


function
 wrap
.
round
(
args
)

	local
 value
 =
 p
.
_cleanNumber
(
args
[
1
]
 or
 args
.
value
 or
 0
)

	local
 precision
 =
 p
.
_cleanNumber
(
args
[
2
]
 or
 args
.
precision
 or
 0
)

	if
 value
 ==
 nil
 or
 precision
 ==
 nil
 then

		return
 err
(
'gia tr? cho vao khong ph?i la s? khi lam tron'
)

	else

		return
 p
.
_round
(
value
,
 precision
)

	end

end


function
 p
.
_round
(
value
,
 precision
)

	local
 rescale
 =
 math.pow
(
10
,
 precision
 or
 0
);

	return
 math.floor
(
value
 *
 rescale
 +
 0.5
)
 /
 rescale
;

end


--[[

log10


tr? v? nh?t ky (c? s? 10) c?a m?t s?


Cach s? d?ng:

{{#invoke:Math | log10 | x }}

]]


function
 wrap
.
log10
(
args
)

	return
 math
.
log10
(
args
[
1
])

end


--[[

mod


Tinh phep mo đun.


Cach s? d?ng:

{{#g?i:Math | mod | x | y }}


--]]


function
 wrap
.
mod
(
args
)

	local
 x
 =
 p
.
_cleanNumber
(
args
[
1
])

	local
 y
 =
 p
.
_cleanNumber
(
args
[
2
])

	if
 not
 x
 then

		return
 err
(
'gia tr? đ?i s? đ?u tien l?y d? khong ph?i la s?'
)

	elseif
 not
 y
 then

		return
 err
(
'gia tr? đ?i s? th? hai l?y d? khong ph?i la s?'
)

	else

		return
 p
.
_mod
(
x
,
 y
)

	end

end


function
 p
.
_mod
(
x
,
 y
)

	local
 ret
 =
 x
 %
 y

	if
 not
 (
0
 <=
 ret
 and
 ret
 <
 y
)
 then

		ret
 =
 0

	end

	return
 ret

end


--[[

gcd


Tinh b?i s? chung nh? nh?t c?a nhi?u s?.


Cach s? d?ng:

{{#g?i:Math | gcd | gia tr? 1 | gia tr? 2 | gia tr? 3 | … }}

--]]


function
 wrap
.
gcd
(
args
)

	return
 p
.
_gcd
(
unpackNumberArgs
(
args
))

end


function
 p
.
_gcd
(...)

	local
 function
 findGcd
(
a
,
 b
)

		local
 r
 =
 b

		local
 oldr
 =
 a

		while
 r
 ~=
 0
 do

			local
 quotient
 =
 math.floor
(
oldr
 /
 r
)

			oldr
,
 r
 =
 r
,
 oldr
 -
 quotient
 *
 r

		end

		if
 oldr
 <
 0
 then

			oldr
 =
 oldr
 *
 -
1

		end

		return
 oldr

	end

	local
 result
,
 count
 =
 fold
(
findGcd
,
 ...)

	return
 result

end


--[[

precision_format


Lam tron s? theo đ? chinh xac đ??c đ?nh ro va đ?nh d?ng s? theo cac quy t?c t?ng

đ??c s? d?ng trong {{b?n m?u:Rnd}}. Gia tr? cho ra la chu?i.


Cach s? d?ng:

{{#g?i: Math | precision_format | s? | đ? chinh xac }}

]]


function
 wrap
.
precision_format
(
args
)

	local
 value_string
 =
 args
[
1
]
 or
 0

	local
 precision
 =
 args
[
2
]
 or
 0

	return
 p
.
_precision_format
(
value_string
,
 precision
)

end


function
 p
.
_precision_format
(
value_string
,
 precision
)

	-- For access to Mediawiki built-in formatter.

	local
 lang
 =
 mw
.
getContentLanguage
();


	local
 value

	value
,
 value_string
 =
 p
.
_cleanNumber
(
value_string
)

	precision
 =
 p
.
_cleanNumber
(
precision
)


	-- Check for non-numeric input

	if
 value
 ==
 nil
 or
 precision
 ==
 nil
 then

		return
 err
(
'gia tr? đ?u vao khong h?p l? khi lam tron'
)

	end


	local
 current_precision
 =
 p
.
_precision
(
value
)

	local
 order
 =
 p
.
_order
(
value
)


	-- Due to round-off effects it is neccesary to limit the returned precision under

	-- some circumstances because the terminal digits will be inaccurately reported.

	if
 order
 +
 precision
 >=
 14
 then

		if
 order
 +
 p
.
_precision
(
value_string
)
 >=
 14
 then

			precision
 =
 13
 -
 order
;

		end

	end


	-- If rounding off, truncate extra digits

	if
 precision
 <
 current_precision
 then

		value
 =
 p
.
_round
(
value
,
 precision
)

		current_precision
 =
 p
.
_precision
(
value
)

	end


	local
 formatted_num
 =
 lang
:
formatNum
(
math.abs
(
value
))

	local
 sign


	-- Use proper unary minus sign rather than ASCII default

	if
 value
 <
 0
 then

		sign
 =
 '?'

	else

		sign
 =
 ''

	end


	-- Handle cases requiring scientific notation

	if
 string.find
(
formatted_num
,
 'E'
,
 1
,
 true
)
 ~=
 nil
 or
 math.abs
(
order
)
 >=
 9
 then

		value
 =
 value
 *
 math.pow
(
10
,
 -
order
)

		current_precision
 =
 current_precision
 +
 order

		precision
 =
 precision
 +
 order

		formatted_num
 =
 lang
:
formatNum
(
math.abs
(
value
))

	else

		order
 =
 0
;

	end

	formatted_num
 =
 sign
 ..
 formatted_num


	-- Pad with zeros, if needed

	if
 current_precision
 <
 precision
 then

		local
 padding

		if
 current_precision
 <=
 0
 then

			if
 precision
 >
 0
 then

				local
 zero_sep
 =
 lang
:
formatNum
(
1.1
)

				formatted_num
 =
 formatted_num
 ..
 zero_sep
:
sub
(
2
,
2
)


				padding
 =
 precision

				if
 padding
 >
 20
 then

					padding
 =
 20

				end


				formatted_num
 =
 formatted_num
 ..
 string.rep
(
'0'
,
 padding
)

			end

		else

			padding
 =
 precision
 -
 current_precision

			if
 padding
 >
 20
 then

				padding
 =
 20

			end

			formatted_num
 =
 formatted_num
 ..
 string.rep
(
'0'
,
 padding
)

		end

	end


	-- Add exponential notation, if necessary.

	if
 order
 ~=
 0
 then

		-- Use proper unary minus sign rather than ASCII default

		if
 order
 <
 0
 then

			order
 =
 '?'
 ..
 lang
:
formatNum
(
math.abs
(
order
))

		else

			order
 =
 lang
:
formatNum
(
order
)

		end


		formatted_num
 =
 formatted_num
 ..
 '<span style="margin:0 .15em 0 .25em">×</span>10<sup>'
 ..
 order
 ..
 '</sup>'

	end


	return
 formatted_num

end


--[[

Ham h? tr? phan tich gia tr? cho vao d??i d?ng s?. N?u gia tr? cho vao co v?

khong ph?i la s?, ham nay th? phan tich no la m?t bi?u th?c ham cu phap.

]]


function
 p
.
_cleanNumber
(
number_string
)

	if
 type
(
number_string
)
 ==
 'number'
 then

		-- We were passed a number, so we don't need to do any processing.

		return
 number_string
,
 tostring
(
number_string
)

	elseif
 type
(
number_string
)
 ~=
 'string'
 or
 not
 number_string
:
find
(
'%S'
)
 then

		-- We were passed a non-string or a blank string, so exit.

		return
 nil
,
 nil
;

	end


	-- Attempt basic conversion

	local
 number
 =
 tonumber
(
number_string
)


	-- If failed, attempt to evaluate input as an expression

	if
 number
 ==
 nil
 then

		local
 success
,
 result
 =
 pcall
(
mw
.
ext
.
ParserFunctions
.
expr
,
 number_string
)

		if
 success
 then

			number
 =
 tonumber
(
result
)

			number_string
 =
 tostring
(
number
)

		else

			number
 =
 nil

			number_string
 =
 nil

		end

	else

		number_string
 =
 number_string
:
match
(
"^%s*(.-)%s*$"
)
 -- String is valid but may contain padding, clean it.

		number_string
 =
 number_string
:
match
(
"^%+(.*)$"
)
 or
 number_string
 -- Trim any leading + signs.

		if
 number_string
:
find
(
'^%-?0[xX]'
)
 then

			-- Number is using 0xnnn notation to indicate base 16; use the number that Lua detected instead.

			number_string
 =
 tostring
(
number
)

		end

	end


	return
 number
,
 number_string

end


--[[

Ham b?c x? ly cac đ?i s? m?t cach c? b?n. Ham nay ch?c ch?n r?ng cac ham đ??c

g?i qua l?nh #g?i co th? s? d?ng khung hi?n t?i ho?c khung m?, va no c?ng c?t

b?t kho?ng cach chung quanh cac đ?i s? va xoa cac đ?i s? tr?ng.

]]


local
 mt
 =
 {
 __index
 =
 function
(
t
,
 k
)

	return
 function
(
frame
)

		if
 not
 getArgs
 then

			getArgs
 =
 require
(
'Mo đun:Arguments'
).
getArgs

		end

		return
 wrap
[
k
](
getArgs
(
frame
))
  -- Argument processing is left to Module:Arguments. Whitespace is trimmed and blank arguments are removed.

	end

end
 }


return
 setmetatable
(
p
,
 mt
)