如何在js计算器上区分十进制逗号和小数点



就像我在标题中所写的那样,我想在js计算器中区分这两种小数,因为它们意味着两种不同的东西。我试着四处阅读,发现了一些关于.toLocalString()的东西,但目前的情况对我来说很困惑,所以我在这里寻求帮助。

首先,默认情况下,js只接受.进行一些操作,我不知道如何使用,进行一些操作。这是两件不同的事情,因为当我尝试做类似10.000 + 2的事情时,结果是12,而不是12.000。我的意思是"一万+二",而不是"十,零+二"。那么,我怎样才能写出像10000或100000这样的数字呢?如何使它们意味着一万、十万ecc.ecc.,并与它们进行一些有意义的操作?

第二,可能会出现将点和逗号结合在一起的情况;大约五万、四十五(50000.45),并用它们进行一些操作。这怎么可能?

第三,这与.,的区别有关,js不会自动在一定数量的数字后面放一些符号来表示千、数十万、百万等等。例如,如果我想写十万,它就不写100,000,而只写100000。当你写这些数字时,如何让它自动写这些逗号?事实上,如果你检查我的代码,switch中有case'.'来检查密钥。我不得不这么说,因为正如我所说的,js不会自动放任何符号,而且,正如我已经说过的,如果你真的试图放一个符号,你只能放.

RECAP:因此,我想做的是,js自动将.放在一千、几十万等之后,以便在代码中去掉case '.'。但是.应该理解为像100.000这样的数字是十万而不是一百,零。最后,我想加上小数的,,就像这次100,000是一百,零一样。

我想仅此而已。我把我的密码留给你。我觉得就可读性和长度而言,这不是"最好的"解决方案,但这是第一个出现的解决方案。我想先让它发挥作用,理解所有应该理解的东西,然后努力让它更可读!

谢谢大家!PS使用空格键打开计算器并使用键盘输入数字!我删除了使鼠标工作的代码。

const keys = document.querySelectorAll('#keys-container div');
const display = document.getElementById('display');
let powerButton = 'OFF';
let number1 = [];
let number2 = [];
let result = undefined;
let operator = undefined;
let decimalPointNumber1 = 'ON';
let decimalPointNumber2 = 'OFF';

window.addEventListener('keydown', function (e) {

switch (e.key) {
case ' ':
powerButton = 'ON';
number1 = [];
number2 = [];
result = undefined;
operator = undefined;
decimalPointNumber1 = 'ON';
decimalPointNumber2 = 'OFF';
display.innerText = '0';
break;
}
if (powerButton === 'ON' /*&& display.innerText.length < 9*/) {
switch (e.key) {
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
case '0':
if (operator === undefined) {
number1.push(e.key);
display.innerText = number1.join('');
break;
}
else if (operator !== undefined) {
number2.push(e.key);
display.innerText = number2.join('');
break;
}

case '+':
case '-':
case '*':
case '/':
if (operator === undefined) {
operator = e.key;
break;
}
else if (operator !== undefined) {
if (result === undefined) {
operate(Number(number1.join('')), Number(number2.join('')), operator);
operator = e.key;
decimalPointNumber2 = 'ON';
break;
}
else if (result !== undefined) {
operate(result, Number(number2.join('')), operator);
operator = e.key;
decimalPointNumber2 = 'ON';
break;
}
}

case '.':
if (number1.length > 0 && decimalPointNumber1 === 'ON' && decimalPointNumber2 === 'OFF') {
number1.push(e.key);
decimalPointNumber1 = 'OFF';
decimalPointNumber2 = 'ON';
display.innerText = number1.join('');
break;
}
else if (number2.length > 0 && decimalPointNumber1 === 'OFF' && decimalPointNumber2 === 'ON') {
number2.push(e.key);
decimalPointNumber2 = 'OFF';
display.innerText = number2.join('');
break;
}
else {
break;
}

case '=':
if (result === undefined) {
operate(Number(number1.join('')), Number(number2.join('')), operator);
}
else if (result !== undefined) {
operate(result, Number(number2.join('')), operator);
}
}
}
});
keys.forEach(key => key.addEventListener('mousedown', function (e) {
key.classList.add('press-div');
}));
keys.forEach(key => key.addEventListener('mouseup', function (e) {
key.classList.remove('press-div');
}));

function operate(n1, n2, operator) {
switch (operator) {
case '+':
result = add(n1, n2);
number2 = [];
console.log(result);
display.innerText = result;
break;
case '-':
result = difference(n1, n2);
number2 = [];
console.log(result);
display.innerText = result;
break;
case '*':
result = multiply(n1, n2);
number2 = [];
console.log(result);
display.innerText = result;
break;
case '/':
result = ratio(n1, n2);
number2 = [];
console.log(result);
display.innerText = result;
break;
}
}
function add(a, b) {
return a + b;
}
function difference(a, b) {
return a - b;
}
function multiply(a, b) {
return a * b;
}
function ratio(a, b) {
return a / b;
}
body {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
background-color: #00162b
}
body > div {
/* border: 1px solid black;*/
box-sizing: border-box;
}
#main-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border: 0.1px solid #252525;
border-bottom: 3px solid #252525;
border-top-right-radius: 20px;
border-top-left-radius: 20px;
border-bottom-right-radius: 20px;
border-bottom-left-radius: 20px;
box-shadow: 0px 0px 20px 4px #e5e4e2;
}
#display-container {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
border-top-left-radius: 20px;
border-top-right-radius: 20px;
height: 142px;
width: 440px;
background-color: #252525;
}
#display-border {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
/*border-bottom: 3px solid #2e2e2e;
box-shadow: 0px 2px 2px 1px black;*/
border-radius: 10px;
height: 85px; /*-5px*/
width: 415px; /*-5px*/
}
#display {
display: flex;
justify-content: flex-end;
align-items: center;
border-top: 1px solid black;
border-right: 2px solid #4d5c43;
border-bottom: none;
border-left: 2px solid #4d5c43;
padding-right: 10px;
box-sizing: border-box;
height: 70px;
width: 400px;
border-radius: 8.5px;
background: linear-gradient(to bottom, #739a59 40%, #a5c590 90%);
box-shadow: inset 0px 2px 2px 1px #384132;
font-family: 'Consolas';
font-size: 50px;
font-weight: bold;

}

#keyboard {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 420px;
width: 440px;
/*border-bottom: 0.1px solid #252525;
border-right: 0.1px solid #252525;
border-left: 0.1px solid #252525;*/
border-bottom-left-radius: 20px;
border-bottom-right-radius: 20px;
background-color: #e5e4e2;
}
#keys-container {
display: flex;
flex-direction: column;
flex-wrap: wrap;
align-items: center;
justify-content: center;
gap: 12px;
border: 0.1px solid #2e2e2e;
/*border-bottom: 3px solid #2e2e2e; /* -1px*/
border-radius: 15px;
/*box-shadow: 0px 2px 2px 0.2px black;*/
height: 377px;
width: 410px;
background-color: #a9a9a9;
}
#keys-container div {
display: flex;
justify-content: center;
align-items: center;
border: 1px solid #313131;
border-bottom: 3px solid #313131;
border-radius: 10px;
box-shadow: inset 0px -1.5px 5px 1px #9f9f9f;
height: 60px;
width: 80px;
font-size: 25px;
font-weight: bold;
background-color: #e5e4e2;
color: black;

transition: 0.01s;
}
#keys-container .press-div {
border-bottom: 1px solid black;
box-shadow: inset 0px -1px 4px 2px #9f9f9f;
margin-top: 2px;

}
<body>
<div id="main-container">
<div id="display-container">
<div id="display-border">
<div id="display"></div>
</div>
</div>

<div id="keyboard">
<div id="keys-container">
<div>ON/C</div>
<div>7</div>
<div>4</div>
<div>1</div>
<div>0</div>
<div>CE</div>
<div>8</div>
<div>5</div>
<div>2</div>
<div>,</div>
<div id="plusorminus">&#177;</div>
<div>9</div>
<div>6</div>
<div>3</div>
<div>&#61;</div>
<div id="ratio">&#247;</div>
<div id="product">&#215;</div>
<div id="difference">&#8722;</div>
<div id="sum" style="height: 136px">&#43;</div>
</div>
</div>
</div>
</body>

想法

您应该将您的逻辑划分为至少两个部分,一个视图和一个控制器。通常,您还会为MVC模式创建一个模型。

但与模式无关,您需要了解应用程序中有一个组件处理显示的内容,另一个组件则处理实际逻辑。

您总是显示strings,从不显示numbers,但您总是使用numbers进行计算,从不使用strings。因此,本质上,您需要在numberstring值之间进行转换。正如您所提到的,number有多种可能的字符串表示形式,具体取决于语言环境。

例如,两个不同地区的相同数字:

  • 在德国(地区:"de de"):10.000,34
  • 在大不列颠(地区:"en-GB"):10000.34

结合上述想法,您的应用程序工作流程将如下所示:

流程看起来像这样:

  1. 用户将值输入为string,视图显示值
  2. 使用正确的语言环境(例如en-GBde-DE)解析stringNumber
  3. 使用控制器中的Number值进行计算并返回值以查看
  4. 使用正确的语言环境将Number格式化为string,例如en-GBde-DE

您知道如何执行13,但缺少24

根据区域设置设置数字格式

对于点4,您可以使用标准JavaScript API:

const germanFormat = new Intl.NumberFormat("de-DE").format(10000.45);
console.log(`- German format:  ${germanFormat}`);
const englishFormat = new Intl.NumberFormat("en-GB").format(10000.45);
console.log(`- English format: ${englishFormat}`)
/* StackOverflow snippet: console should overlap rendered HTML area */
.as-console-wrapper { max-height: 100% !important; top: 0; }

或者使用toLocaleString()

const germanFormat = Number(10000.45).toLocaleString("de-DE");
console.log(`- German format:  ${germanFormat}`);
const englishFormat = Number(10000.45).toLocaleString("en-GB");
console.log(`- English format: ${englishFormat}`)
/* StackOverflow snippet: console should overlap rendered HTML area */
.as-console-wrapper { max-height: 100% !important; top: 0; }

根据区域设置分析数字

对于点2,没有简单的标准JavaScript API。但是,您可以使用这个StackOverflow问题中建议的一些实现。

我在这里使用的是来自Mike Bostock的博客文章:

class NumberParser {
constructor(locale) {
const parts = new Intl.NumberFormat(locale).formatToParts(12345.6);
const numerals = [...new Intl.NumberFormat(locale, {useGrouping: false}).format(9876543210)].reverse();
const index = new Map(numerals.map((d, i) => [d, i]));
this._group = new RegExp(`[${parts.find(d => d.type === "group").value}]`, "g");
this._decimal = new RegExp(`[${parts.find(d => d.type === "decimal").value}]`);
this._numeral = new RegExp(`[${numerals.join("")}]`, "g");
this._index = d => index.get(d);
}
parse(string) {
return (string = string.trim()
.replace(this._group, "")
.replace(this._decimal, ".")
.replace(this._numeral, this._index)) ? +string : NaN;
}
}
const enteredNumber = "10,000.45";
// parse number using german locale
console.log(new NumberParser("de-DE").parse(enteredNumber));
// parse number using british locale
console.log(new NumberParser("en-GB").parse(enteredNumber));
/* StackOverflow snippet: console should overlap rendered HTML area */
.as-console-wrapper { max-height: 100% !important; top: 0; }

确定区域设置

假设您的计算器在浏览器中运行,您可以使用navigator.languages和/或navigator.language来确定用户的区域设置。当然,您也可以创建一个下拉列表或其他内容,让用户选择要使用的区域设置。

function getPreferredBrowserLocale(){
return navigator.languages ? navigator.languages[0]: navigator.language;
}
console.log(getPreferredBrowserLocale())
/* StackOverflow snippet: console should overlap rendered HTML area */
.as-console-wrapper { max-height: 100% !important; top: 0; }

把它放在一起

您可以将这两个操作合并到一个类中,使用首选的语言环境可以很容易地实例化这个类。

class NumberParser {
constructor(locale) {
const parts = new Intl.NumberFormat(locale).formatToParts(12345.6);
const numerals = [...new Intl.NumberFormat(locale, {useGrouping: false}).format(9876543210)].reverse();
const index = new Map(numerals.map((d, i) => [d, i]));
this._group = new RegExp(`[${parts.find(d => d.type === "group").value}]`, "g");
this._decimal = new RegExp(`[${parts.find(d => d.type === "decimal").value}]`);
this._numeral = new RegExp(`[${numerals.join("")}]`, "g");
this._index = d => index.get(d);
this._locale = locale;
}
format(number){
return new Intl.NumberFormat(this._locale).format(number);
}
parse(string) {
return (string = string.trim()
.replace(this._group, "")
.replace(this._decimal, ".")
.replace(this._numeral, this._index)) ? +string : NaN;
}
}
function getPreferredBrowserLocale(){
return navigator.languages ? navigator.languages[0]: navigator.language;
}
const numberParser = new NumberParser(getPreferredBrowserLocale());
console.log(`Number in preferred locale: ${numberParser.format(10000.45)}`)
/* StackOverflow snippet: console should overlap rendered HTML area */
.as-console-wrapper { max-height: 100% !important; top: 0; }

希望这能给你一个如何实现计算器的想法。快乐编码:)

最新更新