use truncation instead of rounding down or rounding to the nearest value when numerical calculations exceed precision limits

This commit is contained in:
MaysWind
2025-09-09 20:46:51 +08:00
parent d4603a1892
commit 7e2e1a4ad3
13 changed files with 36 additions and 36 deletions
@@ -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);
} }
} }
}, },
+1 -1
View File
@@ -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;
+3 -3
View File
@@ -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 {
+3 -3
View File
@@ -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
View File
@@ -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;
+2 -2
View File
@@ -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);
} }
} }
} }
+9 -9
View File
@@ -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);
} }
} }
} }
+2 -2
View File
@@ -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;
} }
+2 -2
View File
@@ -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;
+6 -6
View File
@@ -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})`;