mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-19 01:04:25 +08:00
use truncation instead of rounding down or rounding to the nearest value when numerical calculations exceed precision limits
This commit is contained in:
@@ -181,7 +181,7 @@ export function useAccountBalanceTrendsChartBase(props: CommonAccountBalanceTren
|
|||||||
const minimumBalance = Math.min(...dataItems.map(item => item.accountClosingBalance));
|
const minimumBalance = Math.min(...dataItems.map(item => item.accountClosingBalance));
|
||||||
const maximumBalance = Math.max(...dataItems.map(item => item.accountClosingBalance));
|
const maximumBalance = Math.max(...dataItems.map(item => item.accountClosingBalance));
|
||||||
const medianBalance = dataItems[Math.floor(dataItems.length / 2)].accountClosingBalance;
|
const medianBalance = dataItems[Math.floor(dataItems.length / 2)].accountClosingBalance;
|
||||||
const averageBalance = Math.floor(sumAmounts(dataItems.map(item => item.accountClosingBalance)) / dataItems.length);
|
const averageBalance = Math.trunc(sumAmounts(dataItems.map(item => item.accountClosingBalance)) / dataItems.length);
|
||||||
|
|
||||||
if (props.account.isAsset) {
|
if (props.account.isAsset) {
|
||||||
lastOpeningBalance = openingBalance;
|
lastOpeningBalance = openingBalance;
|
||||||
|
|||||||
@@ -243,7 +243,7 @@ const chartOptions = computed<object>(() => {
|
|||||||
axisPointer: {
|
axisPointer: {
|
||||||
label: {
|
label: {
|
||||||
formatter: (params: CallbackDataParams) => {
|
formatter: (params: CallbackDataParams) => {
|
||||||
return formatAmountToLocalizedNumeralsWithCurrency(Math.floor(params.value as number), props.account.currency);
|
return formatAmountToLocalizedNumeralsWithCurrency(Math.trunc(params.value as number), props.account.currency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -389,7 +389,7 @@ const chartOptions = computed<object>(() => {
|
|||||||
axisPointer: {
|
axisPointer: {
|
||||||
label: {
|
label: {
|
||||||
formatter: (params: CallbackDataParams) => {
|
formatter: (params: CallbackDataParams) => {
|
||||||
return formatAmountToLocalizedNumeralsWithCurrency(Math.floor(params.value as number), props.defaultCurrency);
|
return formatAmountToLocalizedNumeralsWithCurrency(Math.trunc(params.value as number), props.defaultCurrency);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -325,7 +325,7 @@ function confirm(): boolean {
|
|||||||
finalValue = previous - current;
|
finalValue = previous - current;
|
||||||
break;
|
break;
|
||||||
case '×':
|
case '×':
|
||||||
finalValue = Math.round(previous * current / 100);
|
finalValue = Math.trunc(previous * current / 100);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
finalValue = previous;
|
finalValue = previous;
|
||||||
|
|||||||
@@ -42,12 +42,12 @@ function formatCoordinateValue(value: number, positiveDirectionName: string, neg
|
|||||||
if (displayFormat === CoordinateDisplayFormat.DecimalDegrees) {
|
if (displayFormat === CoordinateDisplayFormat.DecimalDegrees) {
|
||||||
return `${prefix}${value.toFixed(6)}${suffix}`;
|
return `${prefix}${value.toFixed(6)}${suffix}`;
|
||||||
} else if (displayFormat === CoordinateDisplayFormat.DecimalMinutes) {
|
} else if (displayFormat === CoordinateDisplayFormat.DecimalMinutes) {
|
||||||
const degrees = Math.floor(value);
|
const degrees = Math.trunc(value);
|
||||||
const minutes = (value - degrees) * 60;
|
const minutes = (value - degrees) * 60;
|
||||||
return `${prefix}${degrees}°${minutes.toFixed(5)}'${suffix}`;
|
return `${prefix}${degrees}°${minutes.toFixed(5)}'${suffix}`;
|
||||||
} else if (displayFormat === CoordinateDisplayFormat.DegreesMinutesSeconds) {
|
} else if (displayFormat === CoordinateDisplayFormat.DegreesMinutesSeconds) {
|
||||||
const degrees = Math.floor(value);
|
const degrees = Math.trunc(value);
|
||||||
const minutes = Math.floor((value - degrees) * 60);
|
const minutes = Math.trunc((value - degrees) * 60);
|
||||||
const seconds = (value - degrees - minutes / 60) * 3600;
|
const seconds = (value - degrees - minutes / 60) * 3600;
|
||||||
return `${prefix}${degrees}°${minutes}'${seconds.toFixed(4)}"${suffix}`;
|
return `${prefix}${degrees}°${minutes}'${seconds.toFixed(4)}"${suffix}`;
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ function normalizeNumber(textualNumber: string): number {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function denormalizeNumberToAmount(num: number): number {
|
function denormalizeNumberToAmount(num: number): number {
|
||||||
return Math.floor(num / normalizedNumberToAmountFactor);
|
return Math.trunc(num / normalizedNumberToAmountFactor);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkNumberRange(num: number): void {
|
function checkNumberRange(num: number): void {
|
||||||
@@ -180,14 +180,14 @@ function evaluatePostfixExpr(tokens: string[]): number | null {
|
|||||||
result = a - b;
|
result = a - b;
|
||||||
break;
|
break;
|
||||||
case '*':
|
case '*':
|
||||||
result = Math.floor(a * b / normalizeFactor);
|
result = Math.trunc(a * b / normalizeFactor);
|
||||||
break;
|
break;
|
||||||
case '/':
|
case '/':
|
||||||
if (b === 0) {
|
if (b === 0) {
|
||||||
logger.warn(`cannot evaluate expression "${tokens.join(' ')}", because division by zero`);
|
logger.warn(`cannot evaluate expression "${tokens.join(' ')}", because division by zero`);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
result = Math.floor(a * normalizeFactor / b);
|
result = Math.trunc(a * normalizeFactor / b);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
|
|||||||
+4
-4
@@ -230,7 +230,7 @@ export function formatNumber(value: number, options: NumberFormatOptions, precis
|
|||||||
|
|
||||||
if (isDefined(precision)) {
|
if (isDefined(precision)) {
|
||||||
const ratio = Math.pow(10, precision);
|
const ratio = Math.pow(10, precision);
|
||||||
const normalizedValue = Math.floor(value * ratio);
|
const normalizedValue = Math.trunc(value * ratio);
|
||||||
const textualValue = numeralSystem.formatNumber(normalizedValue / ratio);
|
const textualValue = numeralSystem.formatNumber(normalizedValue / ratio);
|
||||||
return appendDigitGroupingSymbolAndDecimalSeparator(textualValue, options);
|
return appendDigitGroupingSymbolAndDecimalSeparator(textualValue, options);
|
||||||
} else {
|
} else {
|
||||||
@@ -242,7 +242,7 @@ export function formatNumber(value: number, options: NumberFormatOptions, precis
|
|||||||
export function formatPercent(value: number, precision: number, lowPrecisionValue: string, options: NumberFormatOptions): string {
|
export function formatPercent(value: number, precision: number, lowPrecisionValue: string, options: NumberFormatOptions): string {
|
||||||
const numeralSystem = options.numeralSystem || NumeralSystem.Default;
|
const numeralSystem = options.numeralSystem || NumeralSystem.Default;
|
||||||
const ratio = Math.pow(10, precision);
|
const ratio = Math.pow(10, precision);
|
||||||
const normalizedValue = Math.floor(value * ratio);
|
const normalizedValue = Math.trunc(value * ratio);
|
||||||
|
|
||||||
if (value > 0 && normalizedValue < 1 && lowPrecisionValue) {
|
if (value > 0 && normalizedValue < 1 && lowPrecisionValue) {
|
||||||
const systemDecimalSeparator = DecimalSeparator.Dot.symbol;
|
const systemDecimalSeparator = DecimalSeparator.Dot.symbol;
|
||||||
@@ -262,9 +262,9 @@ export function formatPercent(value: number, precision: number, lowPrecisionValu
|
|||||||
|
|
||||||
export function getAmountWithDecimalNumberCount(amount: number, decimalNumberCount: number): number {
|
export function getAmountWithDecimalNumberCount(amount: number, decimalNumberCount: number): number {
|
||||||
if (decimalNumberCount === 0) {
|
if (decimalNumberCount === 0) {
|
||||||
return Math.floor(amount / 100) * 100;
|
return Math.trunc(amount / 100) * 100;
|
||||||
} else if (decimalNumberCount === 1) {
|
} else if (decimalNumberCount === 1) {
|
||||||
return Math.floor(amount / 10) * 10;
|
return Math.trunc(amount / 10) * 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
return amount;
|
return amount;
|
||||||
|
|||||||
@@ -2187,9 +2187,9 @@ export function useI18n() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (accountsBalance[i].isAsset) {
|
if (accountsBalance[i].isAsset) {
|
||||||
totalBalance += Math.floor(balance);
|
totalBalance += Math.trunc(balance);
|
||||||
} else if (accountsBalance[i].isLiability) {
|
} else if (accountsBalance[i].isLiability) {
|
||||||
totalBalance -= Math.floor(balance);
|
totalBalance -= Math.trunc(balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -510,7 +510,7 @@ export const useAccountsStore = defineStore('accounts', () => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
netAssets += Math.floor(balance);
|
netAssets += Math.trunc(balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -546,7 +546,7 @@ export const useAccountsStore = defineStore('accounts', () => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalAssets += Math.floor(balance);
|
totalAssets += Math.trunc(balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -582,7 +582,7 @@ export const useAccountsStore = defineStore('accounts', () => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
totalLiabilities -= Math.floor(balance);
|
totalLiabilities -= Math.trunc(balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -623,11 +623,11 @@ export const useAccountsStore = defineStore('accounts', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (accountsBalance[i].isAsset) {
|
if (accountsBalance[i].isAsset) {
|
||||||
totalBalance += Math.floor(balance);
|
totalBalance += Math.trunc(balance);
|
||||||
} else if (accountsBalance[i].isLiability) {
|
} else if (accountsBalance[i].isLiability) {
|
||||||
totalBalance -= Math.floor(balance);
|
totalBalance -= Math.trunc(balance);
|
||||||
} else {
|
} else {
|
||||||
totalBalance += Math.floor(balance);
|
totalBalance += Math.trunc(balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -737,11 +737,11 @@ export const useAccountsStore = defineStore('accounts', () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (subAccount.isAsset) {
|
if (subAccount.isAsset) {
|
||||||
totalBalance += Math.floor(balance);
|
totalBalance += Math.trunc(balance);
|
||||||
} else if (subAccount.isLiability) {
|
} else if (subAccount.isLiability) {
|
||||||
totalBalance -= Math.floor(balance);
|
totalBalance -= Math.trunc(balance);
|
||||||
} else {
|
} else {
|
||||||
totalBalance += Math.floor(balance);
|
totalBalance += Math.trunc(balance);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -164,13 +164,13 @@ export const useOverviewStore = defineStore('overview', () => {
|
|||||||
const expenseAmount = exchangeRatesStore.getExchangedAmount(amount.expenseAmount, amount.currency, defaultCurrency);
|
const expenseAmount = exchangeRatesStore.getExchangedAmount(amount.expenseAmount, amount.currency, defaultCurrency);
|
||||||
|
|
||||||
if (isNumber(incomeAmount)) {
|
if (isNumber(incomeAmount)) {
|
||||||
totalIncomeAmount += Math.floor(incomeAmount);
|
totalIncomeAmount += Math.trunc(incomeAmount);
|
||||||
} else {
|
} else {
|
||||||
hasUnCalculatedTotalIncome = true;
|
hasUnCalculatedTotalIncome = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNumber(expenseAmount)) {
|
if (isNumber(expenseAmount)) {
|
||||||
totalExpenseAmount += Math.floor(expenseAmount);
|
totalExpenseAmount += Math.trunc(expenseAmount);
|
||||||
} else {
|
} else {
|
||||||
hasUnCalculatedTotalExpense = true;
|
hasUnCalculatedTotalExpense = true;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -260,7 +260,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
amount = Math.floor(finalAmount);
|
amount = Math.trunc(finalAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (account.isLiability) {
|
if (account.isLiability) {
|
||||||
@@ -481,7 +481,7 @@ export const useStatisticsStore = defineStore('statistics', () => {
|
|||||||
const amount = exchangeRatesStore.getExchangedAmount(item.amount, item.account.currency, defaultCurrency);
|
const amount = exchangeRatesStore.getExchangedAmount(item.amount, item.account.currency, defaultCurrency);
|
||||||
|
|
||||||
if (isNumber(amount)) {
|
if (isNumber(amount)) {
|
||||||
item.amountInDefaultCurrency = Math.floor(amount);
|
item.amountInDefaultCurrency = Math.trunc(amount);
|
||||||
}
|
}
|
||||||
} else if (item.account && item.account.currency === defaultCurrency) {
|
} else if (item.account && item.account.currency === defaultCurrency) {
|
||||||
item.amountInDefaultCurrency = item.amount;
|
item.amountInDefaultCurrency = item.amount;
|
||||||
|
|||||||
@@ -410,9 +410,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
transactionMonthList.totalAmount.expense = Math.floor(totalExpense);
|
transactionMonthList.totalAmount.expense = Math.trunc(totalExpense);
|
||||||
transactionMonthList.totalAmount.incompleteExpense = incomplete || hasUnCalculatedTotalExpense;
|
transactionMonthList.totalAmount.incompleteExpense = incomplete || hasUnCalculatedTotalExpense;
|
||||||
transactionMonthList.totalAmount.income = Math.floor(totalIncome);
|
transactionMonthList.totalAmount.income = Math.trunc(totalIncome);
|
||||||
transactionMonthList.totalAmount.incompleteIncome = incomplete || hasUnCalculatedTotalIncome;
|
transactionMonthList.totalAmount.incompleteIncome = incomplete || hasUnCalculatedTotalIncome;
|
||||||
|
|
||||||
for (const day in transactionMonthList.dailyTotalAmounts) {
|
for (const day in transactionMonthList.dailyTotalAmounts) {
|
||||||
@@ -431,9 +431,9 @@ export const useTransactionsStore = defineStore('transactions', () => {
|
|||||||
const dailyTotalAmount = dailyTotalAmounts[day];
|
const dailyTotalAmount = dailyTotalAmounts[day];
|
||||||
|
|
||||||
transactionMonthList.dailyTotalAmounts[day] = {
|
transactionMonthList.dailyTotalAmounts[day] = {
|
||||||
expense: Math.floor(dailyTotalAmount.expense),
|
expense: Math.trunc(dailyTotalAmount.expense),
|
||||||
incompleteExpense: incomplete || dailyTotalAmount.incompleteExpense,
|
incompleteExpense: incomplete || dailyTotalAmount.incompleteExpense,
|
||||||
income: Math.floor(dailyTotalAmount.income),
|
income: Math.trunc(dailyTotalAmount.income),
|
||||||
incompleteIncome: incomplete || dailyTotalAmount.incompleteIncome
|
incompleteIncome: incomplete || dailyTotalAmount.incompleteIncome
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -568,12 +568,12 @@ export const useTransactionsStore = defineStore('transactions', () => {
|
|||||||
const exchangedNewValue = exchangeRatesStore.getExchangedAmount(newValue, sourceAccount.currency, destinationAccount.currency);
|
const exchangedNewValue = exchangeRatesStore.getExchangedAmount(newValue, sourceAccount.currency, destinationAccount.currency);
|
||||||
|
|
||||||
if (isNumber(decimalNumberCount) && isNumber(exchangedOldValue)) {
|
if (isNumber(decimalNumberCount) && isNumber(exchangedOldValue)) {
|
||||||
oldValue = Math.floor(exchangedOldValue);
|
oldValue = Math.trunc(exchangedOldValue);
|
||||||
oldValue = getAmountWithDecimalNumberCount(oldValue, decimalNumberCount);
|
oldValue = getAmountWithDecimalNumberCount(oldValue, decimalNumberCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isNumber(decimalNumberCount) && isNumber(exchangedNewValue)) {
|
if (isNumber(decimalNumberCount) && isNumber(exchangedNewValue)) {
|
||||||
newValue = Math.floor(exchangedNewValue);
|
newValue = Math.trunc(exchangedNewValue);
|
||||||
newValue = getAmountWithDecimalNumberCount(newValue, decimalNumberCount);
|
newValue = getAmountWithDecimalNumberCount(newValue, decimalNumberCount);
|
||||||
} else {
|
} else {
|
||||||
return;
|
return;
|
||||||
|
|||||||
@@ -196,7 +196,7 @@ export function useTransactionEditPageBase(type: TransactionEditPageType, initMo
|
|||||||
return amountName;
|
return amountName;
|
||||||
}
|
}
|
||||||
|
|
||||||
amountInDefaultCurrency = Math.floor(amountInDefaultCurrency);
|
amountInDefaultCurrency = Math.trunc(amountInDefaultCurrency);
|
||||||
|
|
||||||
const displayAmountInDefaultCurrency = getDisplayAmount(amountInDefaultCurrency, transaction.value.hideAmount, defaultCurrency.value);
|
const displayAmountInDefaultCurrency = getDisplayAmount(amountInDefaultCurrency, transaction.value.hideAmount, defaultCurrency.value);
|
||||||
return amountName + ` (${displayAmountInDefaultCurrency})`;
|
return amountName + ` (${displayAmountInDefaultCurrency})`;
|
||||||
|
|||||||
Reference in New Issue
Block a user