Ошибка многочисленные десятичные точки

Я использую PHPExcel для клиентского проекта, над которым я работаю. Там эта ошибка, с которой я столкнулся, где лишние десятичные разряды добавляются случайным образом для некоторых ячеек при чтении файла excel. Например, вместо 56.25 я получаю 56.24999999999. Я проследил эту проблему непосредственно с PHPExcel, и я потратил много времени на просмотр документации, но я не нашел ничего, что могло бы решить эту проблему. Я не могу просто округлить числа до заданной десятичной точки, потому что это происходит случайным образом, а разные ячейки имеют числа с разными десятичными точками. Пожалуйста, помогите!!!

EDIT: важно, чтобы десятичные точки оставались в точности так, как они были введены вручную. Поэтому, если клиент вручную вводит 34.25 в одну ячейку, а затем 51.3456 в другую ячейку, они должны оставаться такими же! Таким образом, округление не является идеальным решением здесь.

28 янв. 2016, в 08:54

Поделиться

Источник

3 ответа

Прочитав комментарий Марка Бейкера,

Это не случайные; значения десятичного плавания не всегда могут быть представлены точно на компьютеры, использующие двоичное представление… это не проблема PHPExcel или даже проблема с PHP… это хорошо документированная проблема с цифровыми компьютерами; и решения для форматирования предоставляются спринтом() или number_format() —

Я обнаружил, что убедитесь, что все номера сохранены, поскольку текст решает эту проблему. PHP будет читать их как строки, поэтому его странные сфинансы с плавающей запятой не будут проблемой.

ninjacoder
28 янв. 2016, в 16:43

Поделиться

Я также заметил это. Самое быстрое решение, которое сработало для меня, было небольшой модификацией в файле PHPExcel/Calculation.php:

Перейдите к PHPExcel/Calculation.php

Измените $setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16; на низкое значение, например

$setPrecision   = (PHP_INT_SIZE == 4) ? 4 : 4;

anju
09 авг. 2016, в 13:22

Поделиться

Ещё вопросы

  • 0Функция php mail с адреса электронной почты показывает адрес почтового сервера
  • 0Читать XML с ООП PHP
  • 0Как сделать так, чтобы моя программа принимала несколько слов
  • 1Просмотр полноэкранного изображения после нажатия кнопки onClick
  • 1SQL Trigger с Entity Framework
  • 0Google войти с помощью angularjs
  • 1Использование ConcurrentDictionary в веб-сервисе
  • 1Исключение с 64-битным модульным тестом в Visual Studio 2008 Professional
  • 0Как использовать дополнительные значения в маршрутах Laravel?
  • 1Можно ли динамически назначать функции onClick кнопкам?
  • 1NodeJS Websockets — завершить сокет после отправки данных
  • 0Воспроизведение MP3 с петлей в качестве переменной
  • 0Угловая лучшая практика. Действия контроллера, запускающие анимацию
  • 1Как отобразить значения двух массивов и вернуть индекс сопоставленного значения
  • 1C # Reflection: В чем разница между FieldInfo.SetValue () и FieldInfo.SetValueDirect ()?
  • 1Исключение «… целевая машина активно отказалась…» в простом клиент-серверном приложении
  • 0Как настроить высоту угловых данных на основе данных
  • 0Удержание курсора мыши над ручкой при перемещении мыши
  • 0почему nl2br много <br>
  • 0Оценка постфиксного выражения. pop () возвращает неверные значения для вычисления функции
  • 0PHPStorm «Доступ к членам класса при создании экземпляра» phpDoc
  • 0php: невозможно выполнить итерацию для каждого цикла
  • 0как убрать абсолютную позицию с помощью jquery?
  • 0JQuery несколько событий и несколько селекторов
  • 1Как узнать, играет ли звук с помощью C #?
  • 0Включить только если минимум 6 месяцев активности
  • 0поиск подстроки в конце строки в запросе sql
  • 0Когда использовать & в C ++ при объявлении переменных?
  • 1Как разрешить внешний контакт для BottomSheetDialog?
  • 1неизменяемая карта, добавление одного объекта является синтаксической ошибкой, 2 в порядке
  • 0Вложенная функция C ++ с указателем в качестве возвращаемого значения
  • 0обработка параллелизма в cron php
  • 0Возвращаемый массив JS на основе сравнения двух массивов с вложенными элементами
  • 0Как автоматически воспроизводить YouTube видео в HTML iframe в iphone
  • 1Firebase OrderByChild () и EqualTo () не работает должным образом
  • 1C # добавление в список кортежей с функцией
  • 1Обращение к члену в качестве переменной в Discord.py
  • 0обмен изображениями не работает в Safari
  • 0Добавить или удалить класс Css, когда входное значение равно нулю или не равно нулю
  • 0jQPlot Дата на оси X Интервал тика не работает
  • 0AngularJS создает два приложения с одинаковым кодом переднего плана
  • 1Уведомление о флаттере пусто, когда приложение находится в фоновом режиме
  • 0Как управлять вертикальным выпадающим меню при наведении курсора?
  • 1FileLoadException не обработан
  • 0Обновление разделов страницы после замены фильтра
  • 1Добавление нескольких списков в PivotItem в Windows Phone 7
  • 1Вызываемый объект столбца в Dataframe Spark 2.2.1
  • 0Как найти повторяющееся значение значения столбца, используя mysql?
  • 0Неактивная пользовательская функция
  • 0Обновление номера в подсказках jQuery UI

Сообщество Overcoder

Я предполагаю, что created_at — это метка времени?.. Я выбираю date_part(text, timestamp) и date_part(text, interval), если поэтому date_part возвращает double precision, к которой вы пытаетесь применить маску 'YYYY-MM-DD HH24', например:

v=# select date_part('hour', now());
date_part
-----------
9

и я не понимаю, как вы могли бы получить год, месяц, день и час из девяти…

Тем не менее, я предполагаю, что вы хотели применить маску против усеченной даты к точности часов, которая выполняется с помощью date_trunc(text, timestamp):

v=# select date_trunc('hour', now());
date_trunc
------------------------
2017-06-20 09:00:00+01
(1 row)

поэтому теперь вы можете применить формат времени:

v=# select to_char(date_trunc('hour', now()),'YYYY-MM-DD HH24');
to_char
---------------
2017-06-20 09
(1 row)

но если это то, что вы хотите, то вам не нужно урезать время вообще:

v=# select to_char(now(),'YYYY-MM-DD HH24');
to_char
---------------
2017-06-20 09
(1 row)

https://www.postgresql.org/docs/current/static/functions-datetime.html

#sql #postgresql #sqldatatypes

Вопрос:

Я создаю таблицу, подобную этой

 CREATE TABLE foo (
    id serial CONSTRAINT id_pk PRIMARY KEY,
    bar varchar(256),
    test decimal(5,5)
);
 

Затем я хочу заполнить test столбец

  INSERT INTO foo (test) VALUES (12345.12345)
 

Это дает мне

Деталь переполнения числового поля: Поле с точностью 5, масштаб 5, округляется до абсолютного значения менее 1.

Я этого не понимаю. Я подумал , что если я задам столбцу значение decimal(5,5) , у меня должно быть пять цифр слева от запятой и пять цифр справа от запятой. У меня есть это вместе с номером 12345.12345 .

Почему это дает мне эту ошибку?

Комментарии:

1. Потому что десятичная точность-это не то, что вы думаете. Первое число-это общее количество десятичных цифр, а не количество цифр перед разделителем. Ты хочешь decimal(10, 5) .

2. Попробуй с DECIMAL(10,5) . Параметр слева от запятой-общая длина, параметр справа-количество десятичных знаков.

3. psql Тег относится к инструменту командной строки и здесь не имеет значения. Пожалуйста, не добавляйте его

Ответ №1:

Вы неправильно поняли, как работает указание десятичной дроби (и это немного сбивает с толку, я согласен).

Цитата из руководства

Точность числа-это общее количество значащих цифр во всем числе, то есть количество цифр с обеих сторон десятичной точки. Масштаб числа-это количество десятичных цифр в дробной части справа от десятичной точки

Таким образом, первое число определяет общее количество цифр, второе — количество десятичных знаков.

Если вам нужно 5 цифр до десятичной точки и пять после нее, вам нужно использовать decimal(10,5)

Комментарии:

1. @Stophface . . . Просто хочу подчеркнуть: именно так SQL определяет масштаб и точность, поэтому он работает так во всех базах данных, а не только в Postgres.

I’m using PHPExcel for a client project I’m working on. There’s this bug I’ve been facing where extra decimal places are added randomly for some cells while reading the excel file. For example, instead of 56.25, I get 56.24999999999. I’ve traced this problem to PHPExcel itself and I’ve spent a lot of time looking through the documentation but I haven’t found anything that can solve this. I can’t just round off the numbers to a given decimal point because it happens randomly and different cells have numbers with different decimal points. Please help!!!

EDIT: It is critical that the decimal points remain exactly as they were manually input. So if the client manually inputs 34.25 in one cell and then 51.3456 in a other cell, they should remain exactly like that! So rounding off isn’t the ideal solution here.

asked Jan 28, 2016 at 7:18

ninjacoder's user avatar

ninjacoderninjacoder

2932 silver badges11 bronze badges

3

After reading the comment by Mark Baker,

These aren’t random; decimal float values cannot always be represented exactly on
computers that use binary representation…. this is not a PHPExcel problem, or even a PHP problem…. it’s a well-documented digital computer problem; and the solutions for formatting are provided by sprint() or number_format() –

I discovered that making sure all numbers are saved as text solves this problem. PHP will read them as strings hence its weird floating point shenanigans won’t be a problem.

answered Jan 28, 2016 at 14:55

ninjacoder's user avatar

ninjacoderninjacoder

2932 silver badges11 bronze badges

I also noticed this. The quickest solution that worked for me was a small modification in the PHPExcel/Calculation.php file:

Go to PHPExcel/Calculation.php

Change $setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16; to a low value like

$setPrecision   = (PHP_INT_SIZE == 4) ? 4 : 4;

answered Aug 9, 2016 at 12:19

anju's user avatar

anjuanju

58912 silver badges25 bronze badges

If you have OS x86 PHP_INT_SIZE==4 its true, else you have a OS x64.
16 is too long to OS x64.
In my case, I have a OS x64 so I change PHPExcel/Calculation.php

$setPrecision = (PHP_INT_SIZE == 4) ? 14 : 16;

TO

$setPrecision = (PHP_INT_SIZE == 4) ? 14 : 14;

and work!!!

answered Mar 6, 2019 at 17:20

aledo's user avatar

aledoaledo

112 bronze badges

Вопрос:

У меня есть калькулятор JavaScript, который использует следующий код для обработки десятичных точек в поле ввода расчета (также ниже):

$('#button-dot').click(function() {
var lastChar = $('#disp').val().slice(-1);
var firstChar = $('#disp').val().slice(0);
if ($('#disp').hasClass("result")) {
$('#disp').removeClass("result").val("");
addChar(this.form.display,'0' + '.');
}
else if (lastChar == '.'){
// DO NOTHING
}
else if (lastChar == '1' || lastChar == '2' || lastChar == '3' || lastChar == '4' || lastChar == '5' || lastChar == '6' || lastChar == '7' || lastChar == '8' || lastChar == '9' || lastChar == '0' && firstChar != '0'){
addChar(this.form.display,'.');
}
else if (firstChar == '0'){
addChar(this.form.display,'0' + '.');
}
else {
addChar(this.form.display,'0' + '.');
}
$('#disp').removeClass("result");
});

где функция addChar задается:

function addChar(input, character) {
if (input.value == null || input.value == "0" ) {
input.value = character
}
else {
input.value += character
}
};

и поле ввода:

<INPUT NAME="display" ID="disp" VALUE="0" SIZE="28" MAXLENGTH="25"/>

Я хочу улучшить свой код таким образом, чтобы запретить пользователям вводить несколько десятичных знаков в том же количестве (как показано ниже), сохраняя при этом несколько десятичных знаков в строке расчета (также ниже):

Избегайте этого –

enter image description here

Но позвольте этому –

enter image description here

Я просмотрел regex поскольку я понимаю, что решение моей проблемы может каким-то образом повлиять на это, но я не уверен, как его реализовать (мои навыки JavaScript все еще работают!).

Я также думал о разделении строки на любой из операндов (-,+,/,*,%) и проверке каждого элемента результирующего массива на десятичную точку, но я думаю, что это может быть немного грязно.

Есть идеи?

Лучший ответ:

Поэтому я добавил счетчик:

dotCount = 0;

И сделал это для функции button-dot и операндов:

$('#button-dot').click(function() {
var lastChar = $('#disp').val().slice(-1);
var firstChar = $('#disp').val().slice(0);

if (dotCount == 0){
    if ($('#disp').hasClass("result")) {
      $('#disp').removeClass("result").val("");
      addChar(this.form.display,'0' + '.');
    }
    else if (lastChar == '.'){
        // DO NOTHING
    }
    else if (lastChar == '1' || lastChar == '2' || lastChar == '3' || lastChar == '4' || lastChar == '5' || lastChar == '6' || lastChar == '7' || lastChar == '8' || lastChar == '9' || lastChar == '0' && firstChar != '0'){
        addChar(this.form.display,'.');
    }
    else if (firstChar == '0'){
        addChar(this.form.display,'0' + '.');
    }
    else {
        addChar(this.form.display,'0' + '.');
    }
}// END OF dotCount == 0

else if (dotCount == 1){
    //DO NOTHING
}
  $('#disp').removeClass("result");
  dotCount = 1;
});

(используя + в качестве примера):

$('#button-plus').click(function() {
var lastChar = $('#disp').val().slice(-1);
var firstChar = $('#disp').val().slice(0);
if (lastChar == '*' || lastChar == '-' || lastChar == '+' || lastChar == '/' || lastChar == '.' || lastChar == '(' || lastChar == '%'){
    // DO NOTHING
    }
else if (firstChar == '0'){
    // DO NOTHING
    }
else {
  addChar(this.form.display, '+');
  }
  $('#disp').removeClass("result");
  dotCount = 0;
});

Работает как шарм! Спасибо, Кай Кристенсен за противоположную идею.

Ответ №1

Я бы сделал переменную счетчика, а затем добавляю ее к ней каждый раз, когда вы сталкиваетесь с ней . , при каждом возвращении к нулю каждый раз, когда вы находите операнд. Таким образом, если ваш счетчик больше одного в конце цикла for, вы можете предупредить пользователя о том, чтобы избавиться от точки.

Псевдо-код:

// Do this input.length - 1 times:

// store current char in var curChar.
// check if curChar is a dot. If it is, counter++
// check if curChar is an operand. If it is, counter = 0.

// After the for loop, check if counter is 1 or 0. If it is either of
// these, the user entered an acceptable input. Otherwise, they need to
// take out the extra dots.

Ответ №2

Вы можете легко сделать это с помощью одного регулярного выражения:

^(?:(?:d+(?:.d*)?|.d+)(?:[-+/*%]|$))+$

объяснение

 ^                      # Begin of string
(?:                    # Group
(?:                    #  A number
d+
(?: . d* )?
|  . d+
)
(?:
[-+/*%]                # Operator
|                       # or,
$                      # EOS
)
)+                     # End group, do 1 to many times
$                      # End of string

Ответ №3

Для проверки ввода пользователя вы можете использовать следующее регулярное выражение:

^d+(.d+)?([+-*/]d+(.d+)?)*$
  • d+(.d+)? соответствует десятичной
  • [+-*/] соответствует операторам

regex101

$('#disp').on('input', function() {
if (this.value.match(/^d+(.d+)?([+-*/]d+(.d+)?)*$/)) {
$('#status').show();
} else {
$('#status').hide();
}
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<INPUT NAME="display" ID="disp" VALUE="0" SIZE="28" MAXLENGTH="25"/>
<span id="status">OK</span>

Ответ №4

Вы можете вызвать функцию ошибки, если входная строка соответствует d.d+. – цифра, за которой следует десятичное место, затем 1 или более цифр, за которыми следует другая десятичная точка. Если после первой десятичной точки (например, оператора) есть что-либо, кроме цифры, ошибка не будет срабатывать.

regex101

Понравилась статья? Поделить с друзьями:
  • Ошибка многолистовой подачи epson 805
  • Ошибка многолистовой печати epson
  • Ошибка много пены
  • Ошибка мнимое следование это ошибка
  • Ошибка мнимого следования