Warning: Cannot use a scalar value as an array in /home/admin/public_html/forum/include/fm.class.php on line 757

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/include/fm.class.php on line 770

Warning: Invalid argument supplied for foreach() in /home/admin/public_html/forum/topic.php on line 737
Форумы портала PHP.SU :: Формат денег в mysql (decimal)

 PHP.SU

Программирование на PHP, MySQL и другие веб-технологии
PHP.SU Портал     На главную страницу форума Главная     Помощь Помощь     Поиск Поиск     Поиск Яндекс Поиск Яндекс     Вакансии  Пользователи Пользователи


 Страниц (3): [1] 2 3 »   

> Без описания
nepster
Отправлено: 09 Августа, 2013 - 13:51:43
Post Id



Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




Выбрал для денежных операций тип данных decimal.


Начал проверять, все работает, за исключением 1 момента:

PHP:
скопировать код в буфер обмена
  1.        
  2. $money1 = 213.99999;
  3. $money2 = 283;
  4.  
  5. $money = $money1 + $money2; // результат 496.99999
  6.  


пишем в базу, и туда попадает 497.0000, вот это полное кидалово.
Тип данных в mysql decimal(19,4) DEFAULT NULL

Подскажите пожалуйста как сделать так, что бы в базу записывалось значение без округлений
 
 Top
eai
Отправлено: 09 Августа, 2013 - 13:54:33
Post Id



Частый посетитель


Покинул форум
Сообщений всего: 521
Дата рег-ции: Сент. 2009  
Откуда: Петроград


Помог: 10 раз(а)




Округли записываемое значение до точности колонки.

round($data, 4, PHP_ROUND_HALF_DOWN)

ну или точность колонке на мускле увеличь до 5ти знаков

(Отредактировано автором: 09 Августа, 2013 - 13:56:56)

 
 Top
VestCoastman
Отправлено: 09 Августа, 2013 - 13:55:13
Post Id



Посетитель


Покинул форум
Сообщений всего: 374
Дата рег-ции: Дек. 2010  


Помог: 3 раз(а)




Пользуйтесь DOUBLE(19,4)
 
 Top
Мелкий Супермодератор
Отправлено: 09 Августа, 2013 - 13:55:30
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




nepster пишет:
decimal(19,4)

nepster пишет:
213.99999

хм. А чему вы удивляетесь?
(Добавление)
VestCoastman, деньги в форматах с плавающей запятой хранить нельзя.


-----
PostgreSQL DBA
 
 Top
nepster
Отправлено: 09 Августа, 2013 - 14:05:18
Post Id



Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




подскажите пожалуйста как нужно хранить денежные значения, таким образом, что бы не терялись копейки ?

Цитата:

Округли записываемое значение до точности колонки.

round($data, 4, PHP_ROUND_HALF_DOWN)

ну или точность колонке на мускле увеличь до 5ти знаков


Возвращает 497.

5 знаком или 7, в любом случае иногда будут такие моменты когда будет непонятное-кол знаком после точки. При вычислении % или каких-либо операций
 
 Top
eai
Отправлено: 09 Августа, 2013 - 14:23:32
Post Id



Частый посетитель


Покинул форум
Сообщений всего: 521
Дата рег-ции: Сент. 2009  
Откуда: Петроград


Помог: 10 раз(а)




Да чета раунд глючит ... мож проблема и в прокладке ...

Как решение
$money = ((int)($money*10000))/10000;

Да и осторожно при формировании выражения SQL, не знаю каким методом вы его формируете.

(Отредактировано автором: 09 Августа, 2013 - 14:25:25)

 
 Top
DlTA
Отправлено: 09 Августа, 2013 - 14:38:40
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




eai пишет:
Как решение
$money = ((int)($money*10000))/10000;
нет, это не решение

а деньги хранят в целочисленному количестве копеек (ну или что у вас там минимальная единица расчета)
 
 Top
Мелкий Супермодератор
Отправлено: 09 Августа, 2013 - 14:49:54
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




nepster пишет:
будут такие моменты когда будет непонятное-кол знаком после точки. При вычислении % или каких-либо операций

То вам и нужно округлять куда-нибудь до необходимой точности.

nepster пишет:
Возвращает 497.

Разумеется. А что не так? 496.99999 с округлением до 4 знаков после запятой и должно быть 497.


-----
PostgreSQL DBA
 
 Top
eai
Отправлено: 09 Августа, 2013 - 14:51:41
Post Id



Частый посетитель


Покинул форум
Сообщений всего: 521
Дата рег-ции: Сент. 2009  
Откуда: Петроград


Помог: 10 раз(а)




DlTA пишет:
eai пишет:
Как решение
$money = ((int)($money*10000))/10000;
нет, это не решение

а деньги хранят в целочисленному количестве копеек (ну или что у вас там минимальная единица расчета)


Почему не решение, Реально интересно.

А насчет вашего решения , то я бы так и сделал, но вопрос насколько много уже кода и как много надо переделывать.

По уму надо бы специальный тип данных, аля "С фиксированной запятой"
 
 Top
nepster
Отправлено: 09 Августа, 2013 - 14:58:36
Post Id



Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




Собственно как вам такое решение:


PHP:
скопировать код в буфер обмена
  1.            
  2.         $money1 = 213.99999;
  3.         $money2 = 283;
  4.        
  5.         $money = $money1 + $money2; // результат 496.99999
  6.        
  7.         $money = $this->my_number_format($money);
  8.        
  9.  
  10.        if(is_numeric($money))
  11.        {
  12.             echo $money; // 496.9999
  13.            
  14.             Yii::app()->db->createCommand()->update('t3', array(
  15.                 'd'=>$money,
  16.             ));
  17.        }



Все проходит как нужно, теперь функция:

идем на php.net
http://www.php.net/manual/ru/fun...format.php#91047

и немного подстраиваем данную функцию

PHP:
скопировать код в буфер обмена
  1.     function my_number_format($number, $dec_point = '.')
  2.     {
  3.         $was_neg = $number < 0; // Because +0 == -0
  4.         $number = abs($number);
  5.    
  6.         $tmp = explode('.', $number);
  7.         $out = number_format($tmp[0], 0, $dec_point, '');
  8.        
  9.        
  10.         if (isset($tmp[1]))
  11.         {
  12.                
  13.             $rest = $dec_point.substr($tmp[1],0,4);
  14.             $out .= $rest;
  15.         }
  16.    
  17.         if ($was_neg) $out = "-$out";
  18.    
  19.         return $out;
  20.     }




работает как нужно! Вопрос только на сколько корректно будет работать с данным методом
 
 Top
DlTA
Отправлено: 09 Августа, 2013 - 15:02:14
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




eai пишет:
Почему не решение, Реально интересно.
он не помню как я на это попадал, но точность подобных вычислений оставляла желать лучшего
 
 Top
eai
Отправлено: 09 Августа, 2013 - 15:02:27
Post Id



Частый посетитель


Покинул форум
Сообщений всего: 521
Дата рег-ции: Сент. 2009  
Откуда: Петроград


Помог: 10 раз(а)




nepster пишет:
function my_number_format($number, $dec_point = '.')


Попахивает бесовщиной Улыбка
 
 Top
DlTA
Отправлено: 09 Августа, 2013 - 15:04:11
Post Id



Постоянный участник


Покинул форум
Сообщений всего: 2952
Дата рег-ции: Окт. 2010  


Помог: 53 раз(а)




nepster пишет:
  function my_number_format($number, $dec_point = '.')
    {
        $was_neg = $number < 0; // Because +0 == -0
        $number = abs($number);
   
        $tmp = explode('.', $number);
        $out = number_format($tmp[0], 0, $dec_point, '');
       
       
        if (isset($tmp[1]))
        {
               
            $rest = $dec_point.substr($tmp[1],0,4);
            $out .= $rest;
        }
   
        if ($was_neg) $out = "-$out";
   
        return $out;
    }

не смахивает ли это на пятиколесный самокат?
 
 Top
nepster
Отправлено: 09 Августа, 2013 - 15:05:23
Post Id



Частый гость


Покинул форум
Сообщений всего: 195
Дата рег-ции: Июль 2012  


Помог: 0 раз(а)




Смахивает, и при этом я где-то слышал, что в СССР делали все качественно на совесть =)
(Добавление)
По сути такой момент с 9999 в остатке будет встречаться достаточно редко.

А значит эта функция именно для 2 случаев, если в друг при вычислениях будет момент, когда остаток привысит 4 числа и когда в остатке будет 9999.

Собственно это редкие случаи

(Отредактировано автором: 09 Августа, 2013 - 15:08:52)

 
 Top
Мелкий Супермодератор
Отправлено: 09 Августа, 2013 - 15:08:39
Post Id



Активный участник


Покинул форум
Сообщений всего: 11926
Дата рег-ции: Июль 2009  
Откуда: Россия, Санкт-Петербург


Помог: 618 раз(а)




nepster пишет:
на сколько корректно будет работать

Некорректно.
4.00006 должно округляться до 4.0001
1.99997 - до 2
Правила округления давно видели?

Если вам по бизнес-логике нужно округлять в меньшую сторону - floor


-----
PostgreSQL DBA
 
 Top
Страниц (3): [1] 2 3 »
Сейчас эту тему просматривают: 0 (гостей: 0, зарегистрированных: 0)
« Вопросы новичков »


Все гости форума могут просматривать этот раздел.
Только зарегистрированные пользователи могут создавать новые темы в этом разделе.
Только зарегистрированные пользователи могут отвечать на сообщения в этом разделе.
 



Powered by PHP  Powered By MySQL  Powered by Nginx  Valid CSS  RSS

 
Powered by ExBB FM 1.0 RC1. InvisionExBB