Слияние кода завершено, страница обновится автоматически
<!DOCTYPE html> <!-- 使用 HTML5 doctype,不区分大小写 -->
<html lang="zh-cmn-Hans">
<!-- 更加标准的 lang 属性写法 http://zhi.hu/XyIa -->
<head>
<meta charset='utf-8'> <!-- 声明文档使用的字符编码 -->
<title>Matrix!</title>
<!-- <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> -->
<script src="https://cdn.jsdelivr.net/npm/jquery@3.6.0/dist/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/mathjs@10.1.0/lib/browser/math.min.js"></script>
<script src="vue.js"></script>
<!-- <script src="jquery3.6.0.min.js"></script> -->
<style>
.name-input {
width: 2em;
text-align: right;
}
</style>
</head>
<body class="">
<div id="app-2" class="item0">
<button @click="addScope()">增加变量</button>
<table>
<tbody>
<tr v-for="e in scopeList" :key="e.key">
<td><input v-model="e.key" class="name-input" />=</td>
<td>
<textarea v-model="e.val" rows="1" v-on:keyup.enter="autoSizeTextarea"
v-on:keyup.delete="autoSizeTextarea"></textarea>
</td>
</tr>
</tbody>
</table>
<hr>
<div v-for="(m,index) in apMatrix" :key="m.id">
<textarea v-on:keyup.enter="autoSizeTextarea" v-on:keyup.delete="autoSizeTextarea" rows="1"
v-model="m.inputForm"></textarea>
<span v-html="result[m.inputForm]"></span>
<button @click="copyEqDown(index)">向下克隆</button>
<button @click="deleteThisLine(index)">删除本行</button>
</div>
</div>
<script>
// m 行数
// n 列数
function makeMatrix(m, n) {
let data = []
let len = m * n;
for (let i = 0; i < m; i++) {
let row = []
for (let j = 0; j < n; j++) {
row.push(0)
}
data.push(row)
}
return {
m: m,
n: n,
data: data,
get(i, j) {
return this.data[i][j]
},
set(i, j, x) {
this.data[i][j] = x
}
}
}
function makeUnitMatrix(n) {
let a = makeMatrix(n, n)
for (let i = 0; i < n; i++) {
a.set(i, i, 1)
}
return a
}
function matrixMultiplyNumber(c, a) {
if (typeof c !== "number") {
return matrixMultiplyNumber(a, c)
}
let r = makeMatrix(a.m, a.n)
for (let i = 0; i < a.m; i++) {
for (let j = 0; j < a.n; j++) {
r.set(i, j, a.get(i, j) * c)
}
}
return r
}
function canMatrixMultiply(a, b) {
return a.n === b.m
}
function matrixMultiply(a, b) {
let c = makeMatrix(a.m, b.n)
let s = a.n
for (let i = 0; i < a.m; i++) {
for (let j = 0; j < b.n; j++) {
// sum
let sum = 0
for (let k = 0; k < s; k++) {
// console.debug("a[", i, k, "] x b[", k, j, "]")
// console.debug(a.get(i, k), "x", b.get(k, j))
sum += a.get(i, k) * b.get(k, j)
}
// console.debug("set", i, j, "=", sum)
c.set(i, j, sum)
}
}
// console.debug(c.data)
return c
}
function matrixPower(a, n) {
if (n === 0) {
return makeUnitMatrix(a.n)
}
let c = a
if (n === 1) {
return c;
}
for (let i = 1; i < n; i++) {
c = matrixMultiply(a, c)
}
return c
}
function rows2cols(rows) {
let n = rows[0].length
let ret = []
for (let i = 0; i < n; i++) {
ret.push([])
}
for (let i = 0; i < rows.length; i++) {
for (let j = 0; j < n; j++) {
ret[j].push(rows[i][j])
}
}
return ret
}
function matrixTranspose(A) {
let c = makeMatrix(A.n, A.m)
c.data = rows2cols(A.data)
return c
}
function fullpermutate(a) {
var result = [];
if (a.length > 1) {
//遍历每一项
for (var m = 0; m < a.length; m++) {
//拿到当前的元素
var left = [a[m]];
//除当前元素的其他元素组合
var rest = a.slice(0, m).concat(a.slice(m + 1, a.length));
//上一次递归返回的全排列
var preResult = fullpermutate(rest);
//组合在一起
for (var i = 0; i < preResult.length; i++) {
var tmp = left.concat(preResult[i])
result.push(tmp);
}
}
} else if (a.length == 1) {
result.push(a);
}
return result;
}
function toN(start, n) {
let ret = []
for (let i = start; i <= n; i++) {
ret.push(i)
}
return ret;
}
function nixushu(a) {
let cnt = 0;
for (let i = 0; i < a.length - 1; i++) {
for (let j = i + 1; j < a.length; j++) {
if (a[i] > a[j]) cnt++
}
}
return cnt
}
function matrixDet(A) {
if (typeof A === "number")
return A
let n = A.n
let xs = toN(1, n)
let ps = fullpermutate(xs)
let s = 0
for (let p of ps) {
let sign = nixushu(p) % 2 === 0 ? 1 : -1
let prod = p.map((j, i) => A.get(i, j - 1)).reduce((a, b) => a * b)
s += sign * prod
}
return s
}
function removeRowCol(A, row, col) {
let c = makeMatrix(A.m - 1, A.n - 1)
for (let i = 0; i < A.m; i++) {
for (let j = 0; j < A.n; j++) {
if (i !== row && j !== col) {
c.set(i > row ? i - 1 : i, j > col ? j - 1 : j, A.get(i, j))
}
}
}
return c
}
// 代数余子式:cofactor
function cofactor(A, i, j) {
let c = removeRowCol(A, i, j)
return matrixDet(c) * ((i + j) % 2 == 0 ? 1 : -1)
}
// 伴随矩阵
function matrixAdjugate(A) {
let c = makeMatrix(A.m, A.n)
if (A.n === 1) {
c.set(0, 0, 1)
return c
}
for (let i = 0; i < A.m; i++) {
for (let j = 0; j < A.n; j++) {
c.set(i, j, cofactor(A, j, i)) // 转置
}
}
return c
}
// 矩阵求逆
function matrixInverse(A) {
return matrixMultiplyNumber(1 / matrixDet(A), matrixAdjugate(A))
}
//格式化浮点数字符串,保证其有给定的小数位数。其中f是浮点数的字符串常量,size是保留小数位数
function formatfloat(f, size) {
let s1 = f.toString()
let s2 = f.toFixed(size + 1) // 多1位(为财主改需求)
return s1.length < s2.length ? s1 : s2
}
function maxArray(a) {
return Math.max.apply(null, a)
}
function padding(number, length, prefix) {
if (String(number).length >= length) {
return String(number);
}
return padding(prefix + number, length, prefix);
}
function sizeTextarea(elem) {
let CTA = $(elem)
let prev = CTA.prev()
let w = prev.width() + 30
let h = prev.height() + 5
CTA.width(w)
CTA.height(h)
}
var id = 0
function defaultItem() {
id += 1;
return {
id: id,
inputForm: "",
}
}
function copyForm(e) {
id += 1;
return {
id: id,
inputForm: e.inputForm
}
}
function txt2mat(txt) {
let lines = txt.split(/(\r\n)+|\r+|\n+/).filter(
x => x !== "" && x !== undefined)
let rows = []
for (let line of lines) {
let ns = line.split(/\s+/).filter(
x => x !== "" && x !== undefined
)
let row = []
for (let n of ns) {
let i_n = parseFloat(n)
if (i_n === NaN) {
throw new Error("not number")
}
row.push(i_n)
}
rows.push(row)
}
if (rows.length === 1) {
if (rows[0].length === 1) {
return rows[0][0]
}
return rows[0]
}
return rows;
}
function arra2ml(arr) {
let t = []
for (let row of arr) {
let r = []
for (let e of row) {
r.push(`<mtd>${e}</mtd>`)
}
t.push(`<mtr>${r.join("")}</mtr>`)
}
return t.join("");
}
function arr2ml(arr) {
let t = ""
if (Array.isArray(arr[0])) {
t = arra2ml(arr)
} else {
let ts = []
for (let n of arr) {
ts.push(`<mtd><mn>${n}</mn></mtd>`);
}
t = `<mtr>${ts.join("")}</mtr>`
}
return `<mo>[</mo>
<mtable>
${t}
</mtable>
<mo>]</mo>`
}
function toMl(v) {
let r
if (Array.isArray(v)) {
r = `<mo>=</mo>` + arr2ml(v)
} else if (typeof v === "number") {
r = `<mo>=</mo><mn>${v}</mn>`
} else {
r = `<merror>${v}</merror>`
}
return `<math>
<mrow>
${r}
</mrow>
</math>`
}
function initScopeList() {
let s = localStorage.getItem('saveScope') ? JSON.parse(localStorage.getItem('saveScope')) : [];
return s;
}
function initValue() {
if (localStorage.getItem('saveForm')) {
let a = JSON.parse(localStorage.getItem('saveForm'));
for (let e of a) {
id = id < e.id ? e.id : id;
}
id += 1;
return a;
} else {
return [defaultItem()];
}
}
var app2 = new Vue({
el: '#app-2',
methods: {
addScope() {
this.scopeList.push({ key: "", val: "" })
},
autoSizeTextarea(e) {
let textarea = e.target;
textarea.style.height = '1.5em';
textarea.style.height = e.target.scrollHeight + 'px';
},
isValidRows(rows) {
if (rows.length === 0) return false;
let n = rows[0].length
for (let i = 0; i < rows.length; i++) {
if (rows[i].length !== n) {
return false;
}
}
return true
},
rows2matrix(rows) {
let mat = makeMatrix(rows.length, rows[0].length)
mat.data = rows
return mat
},
rows2cols(rows) {
// if (rows.length === 0) {
// return []
// }
let n = rows[0].length
let ret = []
for (let i = 0; i < n; i++) {
ret.push([])
}
for (let i = 0; i < rows.length; i++) {
for (let j = 0; j < n; j++) {
ret[j].push(rows[i][j])
}
}
return ret
},
getRowsWidth(rows, precision) {
let widthMatrix = rows.map(
row => (row.map(
x => formatfloat(x, precision).length)))
let m = this.rows2cols(widthMatrix)
return m.map(col => maxArray(col))
},
matrix2txt(m, precision = 0) {
if (m === undefined) {
return ''
}
if (typeof m === 'string') {
return m
}
if (typeof m === 'number') {
return formatfloat(m, precision)
}
let data = m.data
let width = this.getRowsWidth(data, precision)
return data.map(row => row.map(
(x, j) => padding(formatfloat(x, precision), width[j], " ")
).join(" ")).join("\n")
},
precisionRows(rows) {
return maxArray(rows.map(row => this.precisionArray(row)))
},
precisionArray(a) {
return maxArray(a.map(x => this.precisionNumber(x)))
},
precisionNumber(x) {
let r = /\.\d+$/
let m = x.toString().match(r)
if (m) return m[0].length - 1
return 0
},
addItemLeft(index) {
this.apMatrix[index].unshift(defaultItem())
},
addItemRight(index) {
this.apMatrix[index].push(defaultItem())
},
deleteItem(index, i) {
if (this.apMatrix[index][i].a === "")
this.apMatrix[index].splice(i, 1)
},
copyEqDown(index) {
let a = copyForm(this.apMatrix[index])
this.apMatrix.splice(index + 1, 0, a)
},
copyEqUp(index) {
let a = JSON.parse(JSON.stringify(this.apMatrix[index]))
this.apMatrix.splice(index, 0, a)
},
deleteThisLine(index) {
this.apMatrix.splice(index, 1)
this.saveForms()
},
saveForms() {
let s = JSON.stringify(this.apMatrix)
localStorage.setItem('saveForm', s)
},
saveScope() {
let s = JSON.stringify(this.scopeList)
localStorage.setItem('saveScope', s)
}
},
updated() {
// setTimeout(function () {
// 所有的textarea
// $('.items textarea, .resultTA').map((i, x) => sizeTextarea(x))
// $(' textarea').map((i, x) => sizeTextarea(x))
// }, 100)
// 总体高度
let appDiv = $('#app-2')
let h = appDiv.height()
let H = $(window).height()
if (H > h) {
appDiv.css('padding-top', ((H - h) / 2) + 'px')
}
},
computed: {
scope() {
let s = {}
for (let e of this.scopeList) {
let v = e.val;
if (/[\r\n\s]/.test(v)) {
s[e.key] = txt2mat(v)
} else {
s[e.key] = v;
}
}
this.$nextTick(function () {
this.saveScope();
})
return s;
},
result() {
let res = {}
for (let m of this.apMatrix) {
let f = m.inputForm;
if (f === "") {
res[f] = "";
} else {
let r
try {
r = math.evaluate(f, this.scope);
} catch (e) {
r = `<span>${e.toString()}</span>`;
}
res[f] = toMl(r)
}
}
this.$nextTick(function () {
this.saveForms();
})
return res;
},
},
data: {
inputForm: "",
scopeList: initScopeList(),
// a p s
apMatrix: initValue(),
precisions: [0]
}
})
</script>
</body>
</html>
Вы можете оставить комментарий после Вход в систему
Неприемлемый контент может быть отображен здесь и не будет показан на странице. Вы можете проверить и изменить его с помощью соответствующей функции редактирования.
Если вы подтверждаете, что содержание не содержит непристойной лексики/перенаправления на рекламу/насилия/вульгарной порнографии/нарушений/пиратства/ложного/незначительного или незаконного контента, связанного с национальными законами и предписаниями, вы можете нажать «Отправить» для подачи апелляции, и мы обработаем ее как можно скорее.
Опубликовать ( 0 )