@gordiy015

Почему JavaScript не верно считает числа?

Помогите! JavaScript не правильно считает! Например: 9*23.30=209.70000000000002, а верный ответ: 209.7.
Я так понимаю это из-за формата: IEEE-754

Помогите пожалуйста исправить маленький скрипт! Скрипт ниже!

<script type="text/javascript">
	"use strict";
	 jQuery(function (){
		 $("#numb").change(function(){
			  $("#in").val("Обмен " + $("#paxum").val() + "USD на " + $("#np").val() + ". Номер карты "+ $("#numb").val() + " Способ вывода: " + $("#sys").val());
		 })
		 $("#paxum").change(function(){
			 $("#amount").val($("#paxum").val());
			 $("#in").val("Обмен " + $("#paxum").val() + " USD на " + $("#np").val() + ". Номер счета "+ $("#numb").val() + " Способ вывода: " + $("#sys").val());
			  $.ajax({
				type: "POST",
				url: "price.php",
				dataType: "JSON",
				data: {},
				success: function ( data ) {
				 	if($("#changeout").val() == 1)
					{
						$("#sys").val('Приват24');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['1'])+parseFloat($("#paxum").val())) + " ГРН");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['1'])+parseFloat($("#paxum").val())) + " ГРН");
					}
				 	if($("#changeout").val() == 2)
					{
						$("#sys").val('Visa/Mastercard (Украина)');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['2'])+parseFloat($("#paxum").val()))+ " ГРН");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['2'])+parseFloat($("#paxum").val())) + " ГРН");
					}
				 	if($("#changeout").val() == 3)
					{
						$("#sys").val('Visa/Mastercard (Россия)');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['3'])+parseFloat($("#paxum").val()))+ " РУБ");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['3'])+parseFloat($("#paxum").val())) + " РУБ");	
					}
				 	if($("#changeout").val() == 4)
					{
						$("#sys").val('Webmoney WMR');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['4'])+parseFloat($("#paxum").val()))+ " РУБ");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['4'])+parseFloat($("#paxum").val())) + " РУБ");
					}
				 	if($("#changeout").val() == 5)
					{
						$("#sys").val('Яндекс.Деньги');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['5'])+parseFloat($("#paxum").val()))+ " РУБ");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['5'])+parseFloat($("#paxum").val())) + " РУБ");
					}
					if($("#changeout").val() == 6)
					{
						$("#sys").val('Webmoney WMZ');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['6'])+parseFloat($("#paxum").val()))+ " WMZ");
						$("#newprice").html("Вы получите (временно не работает): " + parseFloat($("#paxum").val()*parseFloat(data['6'])+parseFloat($("#paxum").val())) + " WMZ");
					}
			 	}
		 	 })
		 })
		 $("#changeout").click(function(){
			 $.ajax({
				type: "POST",
				url: "price.php",
				dataType: "JSON",
				data: {},
				success: function ( data ) {
				 	if($("#changeout").val() == 1)
					{
						$("#sys").val('Приват24');
						$("#fix").html('номер карты (куда переводим)');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['1'])+parseFloat($("#paxum").val())) + " ГРН");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['1'])+parseFloat($("#paxum").val())) + " ГРН");
					}
				 	if($("#changeout").val() == 2)
					{
						$("#sys").val('Visa/Mastercard (Украина)');
						$("#fix").html('номер карты (куда переводим)');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['2'])+parseFloat($("#paxum").val()))+ " ГРН");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['2'])+parseFloat($("#paxum").val())) + " ГРН <br>(без учета постоянной комиссии 5 грн за обмен)");
					}
				 	if($("#changeout").val() == 3)
					{
						$("#sys").val('Visa/Mastercard (Россия)');
						$("#fix").html('номер карты (куда переводим)');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['3'])+parseFloat($("#paxum").val()))+ " РУБ");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['3'])+parseFloat($("#paxum").val())) + " РУБ <br>(без учета постоянной комиссии 45 руб за обмен)");	
					}
				 	if($("#changeout").val() == 4)
					{
						$("#sys").val('Webmoney WMR');
						$("#fix").html('номер счета (куда переводим)');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['4'])+parseFloat($("#paxum").val()))+ " РУБ");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['4'])+parseFloat($("#paxum").val())) + " РУБ");
					}
				 	if($("#changeout").val() == 5)
					{
						$("#sys").val('Яндекс.Деньги');
						$("#fix").html('номер счета (куда переводим)');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['5'])+parseFloat($("#paxum").val()))+ " РУБ");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['5'])+parseFloat($("#paxum").val())) + " РУБ");
					}
					if($("#changeout").val() == 6)
					{
						$("#sys").val('Webmoney WMZ');
						$("#fix").html('номер счета (куда переводим)');
						$("#np").val(parseFloat($("#paxum").val()*parseFloat(data['6'])+parseFloat($("#paxum").val()))+ " ");
						$("#newprice").html("Вы получите: " + parseFloat($("#paxum").val()*parseFloat(data['6'])+parseFloat($("#paxum").val())) + " WMZ");
					}
			 }
		 })
	 })
	 })
</script>
  • Вопрос задан
  • 710 просмотров
Решения вопроса 1
@napa3um
Для денег используйте целочисленные вычисления. Например, считайте всё в копейках (или в сотых долях копеек, в зависимости от требований к точности), и только при выводе преобразовывайте в рубли. Для базовой поддержки целочисленных вычислений хватит пары таких функций:

// функция возвращает целое число копеек из строки, представляющей число рублей
function centsFromDollars(str) {
    const parsed = str.match(/^(-?\d+)[\.,]?(\d{0,2})/);
    return parsed ? 100 * parsed[1] + (parsed[2] || 0) : 0;
}

// функция возвращает строку, представляющую число рублей, соответствующую целому числу копеек
function dollarsFromCents(int) {
    const str = String(Math.abs(int));
    const sign = int < 0 '-' : '';
    let cents = str.slice(-2);
    if(cents.length < 2)
        cents = '0' + cents;
    let dollars = str.slice(0, -2);
    if(!dollars)
        dollars = '0';
    return `${sign}${dollars}.${cents}`;
}

console.log(centsFromDollars('23.30')); // 2330
console.log(9 * centsFromDollars('23.30')); // 20970
console.log(dollarsFromCents(9 * centsFromDollars('23.30'))); // '209.70'


Для более серьёзных операций можно рассмотреть библиотеки в стиле https://spin.atomicobject.com/2016/01/04/javascrip... , https://github.com/ikr/money-math , mathjs.org/docs/datatypes/numbers.html , т.п.
Ответ написан
Пригласить эксперта
Ответы на вопрос 3
@bromzh
Drugs-driven development
Javascript всё делает правильно, потому что стандарт. См. www.softelectro.ru/ieee754.html

Либо считай всё в целых числах, либо https://github.com/MikeMcl/decimal.js/
Ответ написан
Комментировать
risentveber
@risentveber
fullstack web developer
После вычисления result возвращайте следующее значение:
Math.round(result * 100) / 100
Ответ написан
Комментировать
victorA
@victorA
Front-End developer
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы