跳转到内容

模組:Complex Number/Dual Number

本页使用了标题或全文手工转换
维基百科,自由的百科全书

这是本页的一个历史版本,由A2569875留言 | 贡献2022年4月25日 (一) 05:54 建立内容为“p={} local sollib = require("Module:Complex_Number/Solver") p.dumath={ abs=function(z) local real, epsilon = p.dumath.readPart(z) if math.abs(epsilon) < 1e-12 then return math.abs(real) end return math.sqrt(real * real) end, floor=function(z) local real, epsilon = p.dumath.readPart(z) return p.dumath.getDualNumber(math.floor(real), math.floor(epsilon)) end, ceil=function(z) local real, epsilon = p.dumath.readPart(z) return p…”的新页面)编辑。这可能和当前版本存在着巨大的差异。

(差异) ←上一修订 | 最后版本 (差异) | 下一修订→ (差异)

p={}
local sollib = require("Module:Complex_Number/Solver")
p.dumath={
	abs=function(z)
		local real, epsilon = p.dumath.readPart(z)
		if math.abs(epsilon) < 1e-12 then return math.abs(real) end
		return math.sqrt(real * real)
	end,
	floor=function(z)
		local real, epsilon = p.dumath.readPart(z)
		return p.dumath.getDualNumber(math.floor(real), math.floor(epsilon)) 
	end,
	ceil=function(z)
		local real, epsilon = p.dumath.readPart(z)
		return p.dumath.getDualNumber(math.ceil(real), math.ceil(epsilon)) 
	end,
	DualNumberMeta = {
		__add = function (op1, op2) 
			local real1, real2 = tonumber(op1) or op1.real, tonumber(op2) or op2.real
			local epsilon1, epsilon2 = (tonumber(op1) and 0) or op1.epsilon, (tonumber(op2) and 0) or op2.epsilon
			return p.dumath.getDualNumber(real1 + real2, epsilon1 + epsilon2) 
		end,
		__sub = function (op1, op2) 
			local real1, real2 = tonumber(op1) or op1.real, tonumber(op2) or op2.real
			local epsilon1, epsilon2 = (tonumber(op1) and 0) or op1.epsilon, (tonumber(op2) and 0) or op2.epsilon
			return p.dumath.getDualNumber(real1 - real2, epsilon1 - epsilon2) 
		end,
		__mul = function (op1, op2) 
			local a, c = tonumber(op1) or op1.real, tonumber(op2) or op2.real
			local b, d = (tonumber(op1) and 0) or op1.epsilon, (tonumber(op2) and 0) or op2.epsilon
			return p.dumath.getDualNumber(a * c, a * d + b * c) 
		end,
		__div = function (op1, op2) 
			local a, c = tonumber(op1) or op1.real, tonumber(op2) or op2.real
			local b, d = (tonumber(op1) and 0) or op1.epsilon, (tonumber(op2) and 0) or op2.epsilon
			return p.dumath.getDualNumber(a/c, (b * c - a * d) / (c*c)) 
		end,
		__mod = function (op1, op2) 
			local x = p.dumath.getDualNumber(tonumber(op1) or op1.real, (tonumber(op1) and 0) or op1.epsilon)
			local y = p.dumath.getDualNumber(tonumber(op2) or op2.real, (tonumber(op2) and 0) or op2.epsilon) 
			return x - y * p.dumath.floor(x / y) 
		end,
		__tostring = function (this) 
			local body = ''
			if this.real ~= 0 then body = tostring(this.real) end
			if this.epsilon ~= 0 then 
				if body ~= '' and this.epsilon > 0 then body = body .. '+' end
				if this.epsilon == -1 then  body = body .. '-' end
				if math.abs(this.epsilon) ~= 1 then body = body .. tostring(this.epsilon) end
				body = body .. 'ε'
			end
			if sollib._isNaN(this.real) or sollib._isNaN(this.epsilon) then body = 'nan' end
			if body == '' then body = '0' end
			return body
		end,
		__unm = function (this)
			return p.dumath.getDualNumber(-this.real, -this.epsilon) 
		end,
		__eq = function (op1, op2)
			local diff_real = math.abs( (tonumber(op1) or op1.real) - (tonumber(op2) or op2.real) )
			local diff_epsilon1 = math.abs( ( (tonumber(op1) and 0) or op1.epsilon) - ( (tonumber(op2) and 0) or op2.epsilon) )
			return diff_real < 1e-12 and diff_epsilon1 < 1e-12
		end,
	},
	readDualNumber = function(z)
		if type(z) == type({}) then --if already be complex number, don't run string find.
			if z.numberType == "dualnumber" then
				return z
			elseif z.numberType == "complex" then
				return p.dumath.getDualNumber(z.real, 0)
			elseif z.numberType == "quaternion" then
				return p.dumath.getDualNumber(z.real, 0)
			end
		elseif type(z) == type(0) then
			return p.dumath.getDualNumber(z, 0)
		end
		return p.dumath.getDualNumber(tonumber(z) or z.real, (tonumber(z) and 0) or z.epsilon)
	end,
	readPart = function(z)
		if type(z) == type({}) and (z.numberType == "dualnumber") then --if already be dual number, don't run string find.
			return z.real, z.epsilon
		elseif type(z) == type({}) and (z.numberType == "complex" or z.numberType == "quaternion") then --if already be complex number, don't run string find.
			return z.real, 0
		elseif type(z) == type(0) then
			return z, 0
		end
		return tonumber(z) or z.real, (tonumber(z) and 0) or z.epsilon
	end,
	ele=function(id)
		local _zero = p.dumath.getDualNumber(0, 0)
		local eles = (p.dumath.elements or {})
		local id_msg = tonumber(tostring(id)) or 0
		return eles[id_msg+1]or _zero
	end,
	getDualNumber = function(real,epsilon)
		DualNumber = {}
		setmetatable(DualNumber,p.dumath.DualNumberMeta) 
		function DualNumber:update()
			self.argument = 0
			self.length = math.sqrt( self.real * self.real )
			if self.epsilon ~= 0 then
				self.argument = self.epsilon / self.real
			else
				if self.real > 0 then self.argument = 0.0 
				else self.argument = math.pi end
			end
		end
		function DualNumber:clean()
			if math.abs(self.real) <= 1e-12 then self.real = 0 end
			if math.abs(self.epsilon) <= 1e-12 then self.epsilon = 0 end
			if math.abs(self.real - math.floor(self.real)) <= 1e-12 then self.real = math.floor(self.real) end
			if math.abs(self.epsilon - math.floor(self.epsilon)) <= 1e-12 then self.epsilon = math.floor(self.epsilon) end
			return self
		end
		DualNumber.real, DualNumber.epsilon = real, epsilon
		DualNumber.numberType = "dualnumber"
		return DualNumber
	end,
	toDualNumber = function(num_str)
		if type(num_str) == type({}) then --if already be dual number, don't run string find.
			if num_str.numberType == "dualnumber" then
				return num_str
			elseif num_str.numberType == "complex" then
				return p.dumath.getDualNumber(num_str.real, 0)
			elseif num_str.numberType == "quaternion" then
				return p.dumath.getDualNumber(num_str.real, 0)
			end
		elseif type(num_str) == type(0) then
			return p.dumath.getDualNumber(num_str, 0)
		elseif type(num_str) == type("string") then
			local check_number = tonumber(num_str)
			if check_number ~= nil then return p.dumath.getDualNumber(check_number, 0) end
		end
		local real, epsilon
		if num_str == nil then return nil end
		if ( type(num_str)==type(0) or ( (type(num_str)==type({"table"})) and type(num_str.real)==type(0) ) ) then
			real, epsilon = tonumber(num_str) or num_str.real, (tonumber(num_str) and 0) or num_str.epsilon
		else real, epsilon = p.dumath.toDualNumberPart(num_str)end
		if real == nil or epsilon == nil then return nil end
		return p.dumath.getDualNumber(real, epsilon)
	end,
	toDualNumberPart = function(num_str)
		local body = ''
		local real, epsilon = 0, 0
		local split_str = mw.text.split(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(
				mw.ustring.gsub(num_str or '','(%d)%s*%*%s*([ε])','%1%2'),
			'%s+',''),'%++([%d%.])',',+%1'),'%++([ε])',',+1%1'),'%-+([%d%.])',',-%1'),'%-+([ε])',',-1%1'),'%*+([%d%.])',',*%1'),'%*+([ε])',',*1%1'),'%/+([%d%.])',',/%1'),'%/+([ε])',',/1%1'),',')
		local first = true
		local continue = false
		for k,v in pairs(split_str) do
			continue = false
			local val = mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.ustring.gsub(mw.text.trim(v),'^(%.)','0%1'),'^([%d%.])','+%1'),'([%+%-])([%d%.])','%1\48%2'),'^([ijkl]+)','+1%1')
			if mw.ustring.find(val,"%/") or mw.ustring.find(val,"%*") then return end

			if val == nil or val == '' then if first == true then first = false continue = true else return end end
			if not continue then
				local num_text = mw.ustring.match(val,"[%+%-][%d%.]+[ε]*")
				if num_text ~= val then return end
				local num_part = tonumber(mw.ustring.match(num_text,"[%+%-][%d%.]+"))
				if num_part == nil then return end
				local f_start, f_end = mw.ustring.find(num_text,"[ε]+")
				local part_str = ''
				if f_start then part_str = mw.ustring.sub(num_text, f_start, f_end) end
				
				if part_str == "" then real = real + num_part -- +1.0
				elseif part_str == "ε" then epsilon = epsilon + num_part -- +ε
				end
			end
		end
		return real, epsilon
	end,
}
return p