Skip to content

Instantly share code, notes, and snippets.

@idiotWu
Last active February 26, 2021 15:33
Show Gist options
  • Star 5 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save idiotWu/dfadf958ee666ac3e5cd41d3311b5329 to your computer and use it in GitHub Desktop.
Save idiotWu/dfadf958ee666ac3e5cd41d3311b5329 to your computer and use it in GitHub Desktop.
const magnitude = {
'十': 1e1,
'百': 1e2,
'千': 1e3,
'万': 1e4,
'亿': 1e8,
};
const num = {};
'零一二三四五六七八九'.split('').forEach((v, i) => {
num[v] = i;
});
const operators = {
'加': '+',
'加上': '+',
'减': '-',
'减去': '-',
'乘': '*',
'乘以': '*',
'除': '/',
'除以': '/'
};
function zh2num(str) {
let res = 0;
let pending = 0;
let floatShift = 0;
for (const c of str) {
if (!pending && c === '十') {
res = 10;
} else if (num.hasOwnProperty(c)) {
if (floatShift) {
res += num[c] * floatShift;
floatShift /= 10;
} else {
pending = num[c];
}
} else if (magnitude.hasOwnProperty(c)) {
if (c === '万' || c === '亿') {
res += pending;
res *= magnitude[c];
} else {
res += pending * magnitude[c];
}
pending = 0;
} else if (c === '点') {
floatShift = 0.1;
} else {
throw new Error(`unknown token: ${c} in ${str}`);
}
}
res += pending;
return res;
}
const 计算 = new Proxy({ stack: [] }, {
get(target, prop, reciever) {
if (prop === '等于') {
const expr = target.stack.join(' ');
const res = eval(expr);
target.stack = [];
return `${expr} = ${res}`;
}
if (operators.hasOwnProperty(prop)) {
target.stack.push(operators[prop]);
} else if (prop.includes('分之')) {
const nums = prop.split('分之').map(zh2num);
target.stack.push(nums[1] + '/' + nums[0]);
} else {
target.stack.push(zh2num(prop));
}
return reciever;
}
});
magnitude = {
'十': 1e1,
'百': 1e2,
'千': 1e3,
'万': 1e4,
'亿': 1e8,
}
num = {c: i for i, c in enumerate('零一二三四五六七八九')}
operators = {
'加': '+',
'加上': '+',
'减': '-',
'减去': '-',
'乘': '*',
'乘以': '*',
'除': '/',
'除以': '/'
}
def zh2num(s):
res = 0
pending = 0
floatShift = 0
for c in s:
if not pending and c == '十':
res = 10
elif c in num:
if floatShift:
res += num[c] * floatShift
floatShift /= 10
else:
pending = num[c]
elif c in magnitude:
if c in '万亿':
res += pending
res *= magnitude[c]
else:
res += pending * magnitude[c]
pending = 0
elif c == '点':
floatShift = 0.1
else:
raise ArithmeticError(f'unknow token: {c} in {str}')
res += pending
return res
class ZhCalc:
def __init__(self):
self.stack = []
self.dangling = False
def __getattr__(self, attr):
if attr[0] == '_':
return
if attr in operators:
self.dangling = True
self.stack.append(operators[attr])
else:
if not self.dangling:
self.stack.clear()
else:
self.dangling = False
if '分之' in attr:
vals = [zh2num(s) for s in attr.split('分之')]
self.stack.append(vals[1] + '/' + vals[0])
else:
self.stack.append(zh2num(attr))
return self
def __repr__(self):
expr = ' '.join(str(v) for v in self.stack)
try:
res = eval(expr)
return f'{expr} = {res}'
except Exception:
return expr
计算 = ZhCalc()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment