我怎样才能以短格式显示浮点数并且仍然能够在此 Vue 应用程序中进行计算?

How can I display floating point numbers in a short format and still be able to do calculations in this Vue application?

我正在使用 Vue 3 和一些自定义开发一个小型计算器应用程序 CSS。

据我所知,它工作正常,除了显示长数字作为结果

const calculatorApp = {
  data() {
    return {
      operationsTrack: [],
      operations: [],
      calculation: null,
      currentVal: "",
      isOperatorClicked: false,
      isEquaSignClicked: false
    };
  },
  methods: {
    appendDot() {
      if (this.currentVal.indexOf(".") === -1) {
        this.appendNumber(".");
      }
    },
    appendNumber(clickedVal) {
      if (this.isOperatorClicked) {
        this.currentVal = "";
        this.isOperatorClicked = false;
      }

      if (!this.isEquaSignClicked) {
        this.currentVal = `${this.currentVal}${clickedVal}`;
      } else {
        this.currentVal = clickedVal;
        this.operationsTrack = [];
      }

      this.operationsTrack.push(clickedVal);
    },
    doOperation(operator, operatorLabel) {
      this.isEquaSignClicked = false;
      this.isOperatorClicked = true;
      this.operations.push(this.currentVal);
      this.operations.push(operator);
      this.operationsTrack.push(operatorLabel);
    },
    doCalculation() {
      // push the last value to the operations array
      this.operations.push(this.currentVal);

      let opt = this.operations.map((i) => {
        if (!isNaN(i)) {
          return Number(i);
        }
        return i;
      });

      // Make the calulations string
      this.calculation = opt.join(" ");

      // Compute the calculations
      this.currentVal = eval(this.calculation);

      // Empty the operations array
      this.operations = [];

      // Update equal sign flag
      this.isEquaSignClicked = true;
    },
    clearDisplay() {
      this.currentVal = "";
      this.operations = [];
      this.operationsTrack = [];
      this.calculation = null;
      this.isOperatorClicked = false;
      this.isEquaSignClicked = false;
    }
  },
  computed: {
    operationsTrackDisplay() {
      return this.operationsTrack.join(" ");
    }
  }
};
Vue.createApp(calculatorApp).mount("#myCalculator");
body {
  padding: 0;
  margin: 0;
}

body * {
  box-sizing: border-box;
}

.container {
  min-height: 100vh;
}

.calculator {
  font-family: Montserrat, sans-serif;
  width: 100%;
  max-width: 360px;
  min-width: 300px;
  margin: 10px auto;
  padding: 36px;
  background: #efefef;
  border-radius: 10px;
}

.display {
  position: relative;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  background: #c3c3c3;
  border-radius: 10px;
  margin-bottom: 34px;
  padding: 10px 20px;
}

.result,
.track {
  display: flex;
  justify-content: flex-end;
}

.result {
  margin-top: 3px;
  font-size: 48px;
}

.track {
  position: absolute;
  top: 5px;
  left: 20px;
  right: 20px;
  font-size: 12px;
}

.buttons-container ol {
  list-style-type: none;
  padding: 0;
  margin: 0;
  color: #242424;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 10px;
  row-gap: 10px;
}

.buttons-container li,
.buttons-container .clear {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 36px;
  height: 60px;
  font-weight: 600;
  background: #e7e7e7;
  border-radius: 7px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
}

.buttons-container li {
  width: 60px;
}

.buttons-container .clear {
  margin-top: 10px;
  text-transform: uppercase;
  font-weight: 600;
}

.buttons-container .orange {
  background: #ff9800;
  color: #fff;
}
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500,600&display=swap" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>

<div class="container">
  <div class="calculator" id="myCalculator">
    <div class="display">
      <div class="track">
        <span>{{operationsTrack.length ? operationsTrackDisplay + ' =' : ''}}</span>
      </div>
      <div class="result">
        {{currentVal || 0}}
      </div>
    </div>
    <div class="buttons-container">
      <ol>
        <li @click="appendNumber('7')">7</li>
        <li @click="appendNumber('8')">8</li>
        <li @click="appendNumber('9')">9</li>
        <li @click="doOperation('/', '&divide;')">&divide;</li>
        <li @click="appendNumber('4')">4</li>
        <li @click="appendNumber('5')">5</li>
        <li @click="appendNumber('6')">6</li>
        <li @click="doOperation('*', '&times;')">&times;</li>
        <li @click="appendNumber('1')">1</li>
        <li @click="appendNumber('2')">2</li>
        <li @click="appendNumber('3')">3</li>
        <li @click="doOperation('-', '-')">-</li>
        <li @click="appendNumber('0')">0</li>
        <li @click="appendDot('.')">&middot;</li>
        <li @click="doOperation('+', '+')">+</li>
        <li @click="doCalculation" class="orange">=</li>
      </ol>
      <div @click="clearDisplay" class="clear orange">Clear</div>
    </div>
  </div>
</div>

问题

导致长浮点数的算术运算,例如导致 1.66666666666666671 5 ÷ 9 具有拉伸显示的不便。

将其用作解决方案是个坏主意,因为 toFixed() 转换为字符串 :

 <div class="result">
    {{currentVal.toFixed(6) || 0}}
  </div> 

方便显示长浮动的可行方案是什么?

如果您在计算函数中进行此更改,它将保持为数字

this.currentVal = parseFloat(eval(this.calculation).toFixed(6));

const calculatorApp = {
  data() {
    return {
      operationsTrack: [],
      operations: [],
      calculation: null,
      currentVal: "",
      isOperatorClicked: false,
      isEquaSignClicked: false
    };
  },
  methods: {
    appendDot() {
      if (this.currentVal.indexOf(".") === -1) {
        this.appendNumber(".");
      }
    },
    appendNumber(clickedVal) {
      if (this.isOperatorClicked) {
        this.currentVal = "";
        this.isOperatorClicked = false;
      }

      if (!this.isEquaSignClicked) {
        this.currentVal = `${this.currentVal}${clickedVal}`;
      } else {
        this.currentVal = clickedVal;
        this.operationsTrack = [];
      }

      this.operationsTrack.push(clickedVal);
    },
    doOperation(operator, operatorLabel) {
      this.isEquaSignClicked = false;
      this.isOperatorClicked = true;
      this.operations.push(this.currentVal);
      this.operations.push(operator);
      this.operationsTrack.push(operatorLabel);
    },
    doCalculation() {
      // push the last value to the operations array
      this.operations.push(this.currentVal);

      let opt = this.operations.map((i) => {
        if (!isNaN(i)) {
          return Number(i);
        }
        return i;
      });

      // Make the calulations string
      this.calculation = opt.join(" ");
      // Compute the calculations
      this.currentVal = parseFloat(eval(this.calculation).toFixed(6));
      // Empty the operations array
      this.operations = [];
      // Update equal sign flag
      this.isEquaSignClicked = true;
    },
    clearDisplay() {
      this.currentVal = "";
      this.operations = [];
      this.operationsTrack = [];
      this.calculation = null;
      this.isOperatorClicked = false;
      this.isEquaSignClicked = false;
    }
  },
  computed: {
    operationsTrackDisplay() {
      return this.operationsTrack.join(" ");
    }
  }
};
Vue.createApp(calculatorApp).mount("#myCalculator");
body {
  padding: 0;
  margin: 0;
}

body * {
  box-sizing: border-box;
}

.container {
  min-height: 100vh;
}

.calculator {
  font-family: Montserrat, sans-serif;
  width: 100%;
  max-width: 360px;
  min-width: 300px;
  margin: 10px auto;
  padding: 36px;
  background: #efefef;
  border-radius: 10px;
}

.display {
  position: relative;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  background: #c3c3c3;
  border-radius: 10px;
  margin-bottom: 34px;
  padding: 10px 20px;
}

.result,
.track {
  display: flex;
  justify-content: flex-end;
}

.result {
  margin-top: 3px;
  font-size: 48px;
}

.track {
  position: absolute;
  top: 5px;
  left: 20px;
  right: 20px;
  font-size: 12px;
}

.buttons-container ol {
  list-style-type: none;
  padding: 0;
  margin: 0;
  color: #242424;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 10px;
  row-gap: 10px;
}

.buttons-container li,
.buttons-container .clear {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 36px;
  height: 60px;
  font-weight: 600;
  background: #e7e7e7;
  border-radius: 7px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
}

.buttons-container li {
  width: 60px;
}

.buttons-container .clear {
  margin-top: 10px;
  text-transform: uppercase;
  font-weight: 600;
}

.buttons-container .orange {
  background: #ff9800;
  color: #fff;
}
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500,600&display=swap" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>

<div class="container">
  <div class="calculator" id="myCalculator">
    <div class="display">
      <div class="track">
        <span>{{operationsTrack.length ? operationsTrackDisplay + ' =' : ''}}</span>
      </div>
      <div class="result">
        {{currentVal || 0}}
      </div>
    </div>
    <div class="buttons-container">
      <ol>
        <li @click="appendNumber('7')">7</li>
        <li @click="appendNumber('8')">8</li>
        <li @click="appendNumber('9')">9</li>
        <li @click="doOperation('/', '&divide;')">&divide;</li>
        <li @click="appendNumber('4')">4</li>
        <li @click="appendNumber('5')">5</li>
        <li @click="appendNumber('6')">6</li>
        <li @click="doOperation('*', '&times;')">&times;</li>
        <li @click="appendNumber('1')">1</li>
        <li @click="appendNumber('2')">2</li>
        <li @click="appendNumber('3')">3</li>
        <li @click="doOperation('-', '-')">-</li>
        <li @click="appendNumber('0')">0</li>
        <li @click="appendDot('.')">&middot;</li>
        <li @click="doOperation('+', '+')">+</li>
        <li @click="doCalculation" class="orange">=</li>
      </ol>
      <div @click="clearDisplay" class="clear orange">Clear</div>
    </div>
  </div>
</div>

一种方法是添加另一个计算方法 - 例如result 将以三种格式之一显示数字,并且不会更改 currentVal:

中的值
  1. 科学格式-如果数字是1M或更多-使用Number.toExponential()

  2. 整数 - 没有尾数 - 当 Number.isInteger() returns true

  3. 有限位数的浮点数-当字符串表示的长度小于调用时字符串表示的长度调用.toFixed()

  4. 具有固定格式的浮点数 - 来自调用 .toFixed()


computed:
  result() {
    const number = +this.currentVal;
    if (number > 999999) { 
      return number.toExponential(4);
    }
    if (Number.isInteger(number)) {
      return this.currentVal;
    }
    const fixed = number.toFixed(6);
    if (fixed.length > this.currentVal.length) {
      return this.currentVal;
    }
    return fixed; 
  }

这样就可以随意显示了。

const calculatorApp = {
  data() {
    return {
      operationsTrack: [],
      operations: [],
      calculation: null,
      currentVal: "",
      isOperatorClicked: false,
      isEquaSignClicked: false
    };
  },
  methods: {
    appendDot() {
      if (this.currentVal.indexOf(".") === -1) {
        this.appendNumber(".");
      }
    },
    appendNumber(clickedVal) {
      if (this.isOperatorClicked) {
        this.currentVal = "";
        this.isOperatorClicked = false;
      }

      if (!this.isEquaSignClicked) {
        this.currentVal = `${this.currentVal}${clickedVal}`;
      } else {
        this.currentVal = clickedVal;
        this.operationsTrack = [];
      }

      this.operationsTrack.push(clickedVal);
    },
    doOperation(operator, operatorLabel) {
      this.isEquaSignClicked = false;
      this.isOperatorClicked = true;
      this.operations.push(this.currentVal);
      this.operations.push(operator);
      this.operationsTrack.push(operatorLabel);
    },
    doCalculation() {
      // push the last value to the operations array
      this.operations.push(this.currentVal);

      let opt = this.operations.map((i) => {
        if (!isNaN(i)) {
          return Number(i);
        }
        return i;
      });

      // Make the calulations string
      this.calculation = opt.join(" ");

      // Compute the calculations
      this.currentVal = eval(this.calculation);

      // Empty the operations array
      this.operations = [];

      // Update equal sign flag
      this.isEquaSignClicked = true;
    },
    clearDisplay() {
      this.currentVal = "";
      this.operations = [];
      this.operationsTrack = [];
      this.calculation = null;
      this.isOperatorClicked = false;
      this.isEquaSignClicked = false;
    }
  },
  computed: {
    operationsTrackDisplay() {
      return this.operationsTrack.join(" ");
    },    
    result() {
      const number = +this.currentVal;
      if (number > 999999) { 
        return number.toExponential(4);
      }
      if (Number.isInteger(number)) {
        return this.currentVal;
      }
      const fixed = number.toFixed(6);
      if (fixed.length > this.currentVal.length) {
          return this.currentVal;
      }
      return fixed; 
    }
  }
};
Vue.createApp(calculatorApp).mount("#myCalculator");
body {
  padding: 0;
  margin: 0;
}

body * {
  box-sizing: border-box;
}

.container {
  min-height: 100vh;
}

.calculator {
  font-family: Montserrat, sans-serif;
  width: 100%;
  max-width: 360px;
  min-width: 300px;
  margin: 10px auto;
  padding: 36px;
  background: #efefef;
  border-radius: 10px;
}

.display {
  position: relative;
  font-weight: bold;
  display: flex;
  flex-direction: column;
  background: #c3c3c3;
  border-radius: 10px;
  margin-bottom: 34px;
  padding: 10px 20px;
}

.result,
.track {
  display: flex;
  justify-content: flex-end;
}

.result {
  margin-top: 3px;
  font-size: 48px;
}

.track {
  position: absolute;
  top: 5px;
  left: 20px;
  right: 20px;
  font-size: 12px;
}

.buttons-container ol {
  list-style-type: none;
  padding: 0;
  margin: 0;
  color: #242424;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  column-gap: 10px;
  row-gap: 10px;
}

.buttons-container li,
.buttons-container .clear {
  display: flex;
  justify-content: center;
  align-items: center;
  font-size: 36px;
  height: 60px;
  font-weight: 600;
  background: #e7e7e7;
  border-radius: 7px;
  border: 1px solid rgba(0, 0, 0, 0.1);
  cursor: pointer;
}

.buttons-container li {
  width: 60px;
}

.buttons-container .clear {
  margin-top: 10px;
  text-transform: uppercase;
  font-weight: 600;
}

.buttons-container .orange {
  background: #ff9800;
  color: #fff;
}
<link href="https://fonts.googleapis.com/css2?family=Montserrat:wght@400;500,600&display=swap" rel="stylesheet">
<script src="https://unpkg.com/vue@next"></script>

<div class="container">
  <div class="calculator" id="myCalculator">
    <div class="display">
      <div class="track">
        <span>{{operationsTrack.length ? operationsTrackDisplay + ' =' : ''}}</span>
      </div>
      <div class="result">
        {{ result || 0}}
      </div>
    </div>
    <div class="buttons-container">
      <ol>
        <li @click="appendNumber('7')">7</li>
        <li @click="appendNumber('8')">8</li>
        <li @click="appendNumber('9')">9</li>
        <li @click="doOperation('/', '&divide;')">&divide;</li>
        <li @click="appendNumber('4')">4</li>
        <li @click="appendNumber('5')">5</li>
        <li @click="appendNumber('6')">6</li>
        <li @click="doOperation('*', '&times;')">&times;</li>
        <li @click="appendNumber('1')">1</li>
        <li @click="appendNumber('2')">2</li>
        <li @click="appendNumber('3')">3</li>
        <li @click="doOperation('-', '-')">-</li>
        <li @click="appendNumber('0')">0</li>
        <li @click="appendDot('.')">&middot;</li>
        <li @click="doOperation('+', '+')">+</li>
        <li @click="doCalculation" class="orange">=</li>
      </ol>
      <div @click="clearDisplay" class="clear orange">Clear</div>
    </div>
  </div>
</div>