Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Floating point issues #17

Closed
fedemengo-genuino opened this issue May 18, 2021 · 3 comments
Closed

Floating point issues #17

fedemengo-genuino opened this issue May 18, 2021 · 3 comments

Comments

@fedemengo-genuino
Copy link

fedemengo-genuino commented May 18, 2021

I wrote this simple script using version 2.5.0

const { convert } = require('cashify')

const rates = {
	"USD": 1,
	"EUR": 0.8235,
}

console.log(convert(1, {from: "USD", to: "EUR", rates}))

And the output is 0.8234999999999999. I was expecting to received 0.8235, if I run console.log(convert(10, {from: "USD", to: "EUR", rates})) I get a nice value of 8.235.

@fedemengo-genuino
Copy link
Author

@xxczaki do you have any idea what could be wrong?

@Richienb
Copy link
Contributor

When converting currencies, the input value is automatically multiplied by 100 then divided by 100 after the computation:

https://github.com/xxczaki/cashify/blob/530857c4ceaf98239c9fc45739e511aa8e8c7ea8/src/convert.ts#L26-L29

Because of a JavaScript quirk, 82.35 / 100 === 0.8234999999999999. To fix this problem, a library like big.js can be used until the decimal proposal is completed:

import getRate from './lib/get-rate';
import {Options} from './lib/options';
import parse from './utils/parser';
+import Big from 'big.js';

/**
 * Function, which converts currencies based on provided rates.
 *
 * @param {number | string} amount - Amount of money you want to convert.
 * @param {Object} options - Conversion options.
 * @return {number} Conversion result.
 *
 * @example
 * const rates = {
 * 	GBP: 0.92,
 * 	EUR: 1.00,
 * 	USD: 1.12
 * };
 *
 * convert(10, {from: 'EUR', to: 'GBP', base: 'EUR', rates}); //=> 9.2
 */
export default function convert(amount: number | string, {from, to, base, rates}: Options): number {
	// If provided `amount` is a string, use parsing
	if (typeof amount === 'string') {
		const data = parse(amount);

-		return (data.amount * 100) * getRate(base, rates, data.from ?? from, data.to ?? to) / 100;
+		from = data.from ?? from;
+		to = data.to ?? to;
	}

-	return (amount * 100) * getRate(base, rates, from, to) / 100;
+	return new Big(amount).multiply(getRate(base, rates, from, to)).toNumber();
}

@xxczaki
Copy link
Member

xxczaki commented Dec 5, 2021

Sorry for the inactivity! I just released 3.0.0 with many improvements, including integration with big.js 😄

@xxczaki xxczaki closed this as completed Dec 5, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants