За последние 24 часа нас посетили 17860 программистов и 1600 роботов. Сейчас ищут 843 программиста ...

округление переменной типа float с заданной точностью

Тема в разделе "Прочие вопросы по PHP", создана пользователем Device, 26 фев 2009.

  1. Device

    Device Активный пользователь

    С нами с:
    16 янв 2009
    Сообщения:
    28
    Симпатии:
    0
    Адрес:
    Саратов
    ситуация такая, есть переменная $a=24.1236666 как ее округлить максимально точно с точностью до второго знака? метод round($a)*100/100 не подойдет так как он очень не точно округляет,

    смысл какой, у меня есть несколько пользоваетлей у которых в БД есть ячейка в которую пишется их процент(не важно чего) при изменении процента одного меняется процент всех других тобишь было 1=>25 2=>25 3=>25 4=>25 потом у первого стало 1=>16 следовательно 2=>28 3=>28 4=>28 так вот способ round($a)*100/100 не прокатывает так как после изменения 25 например на 21,22 погрешность может составлять 2 процента, а мне нужна точность до второго знака. Всем заранее спасибо.
     
  2. Mr.M.I.T.

    Mr.M.I.T. Старожил

    С нами с:
    28 янв 2008
    Сообщения:
    4.586
    Симпатии:
    1
    Адрес:
    у тебя канфетка?
  3. Device

    Device Активный пользователь

    С нами с:
    16 янв 2009
    Сообщения:
    28
    Симпатии:
    0
    Адрес:
    Саратов
    спасибо, неуглядел :) в мануале :)
     
  4. Device

    Device Активный пользователь

    С нами с:
    16 янв 2009
    Сообщения:
    28
    Симпатии:
    0
    Адрес:
    Саратов
    В общем еще больше погрешность теперь :(

    вот код:
    Код (Text):
    1.     $newPercent = $_GET['val']; //Новый процент
    2.     $res = mysql_query("SELECT * FROM `default`");
    3.     $allMoney = (float)mysql_result($res, 0, 'money'); //Весь капитал
    4.     $res = mysql_query("SELECT * FROM `clients` WHERE `id`='$id'");
    5.     $currPercent = mysql_result($res, 0, 'percent'); //Текщий процент клиента
    6.     $currMoneyUser = $allMoney*$currPercent/100; //Текущий баланс клиента
    7.     if($currPercent > $newPercent){ //при снятии денег
    8.       $diffSumm = $allMoney*($currPercent-$newPercent)/100; //сумма к снятию
    9.       $newCapital = $allMoney-$diffSumm; //измененный капитал
    10.       $res = mysql_query("SELECT * FROM `clients`");
    11.       for($i=0;$i<mysql_num_rows($res);$i++){
    12.         $f = mysql_fetch_assoc($res);
    13.         if($f['id'] != $id){
    14.           $currInvest = $allMoney*$f['percent']/100;
    15.           $newPercentUser = $currInvest*100/$newCapital;
    16.           $query = "UPDATE `clients` SET `percent`='$newPercentUser' WHERE `id`='".$f['id']."'";
    17.           mysql_query($query) or die("Ошибка:".mysql_error());
    18.         }
    19.       }
    20.       mysql_query("UPDATE `clients` SET `percent`='$newPercent' WHERE `id`='$id'") or die("Ошибка:".mysql_error());
    21.     }
    и например при изменении процента первого с 25 на 16 погрешность составляет 2 процента :(
     
  5. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    извечная проблема округления при расчетах бабла.

    делают так. считают все изменения без одного, а потом от общего кол-ва отнимают сумму и впаривают последнему.
     
  6. Device

    Device Активный пользователь

    С нами с:
    16 янв 2009
    Сообщения:
    28
    Симпатии:
    0
    Адрес:
    Саратов
    ну 2 процента это серьезно, т.к. если сумма 1000000 рублей то погрешность: 20000 рублей
     
  7. делают поле DECIMAL, хранят все суммы в копейках, потом перед выводом делят на 100.
     
  8. Device

    Device Активный пользователь

    С нами с:
    16 янв 2009
    Сообщения:
    28
    Симпатии:
    0
    Адрес:
    Саратов
    так у меня в БД хранится не сумма бабла а процент от общего капитала, а общий капитал это сумма крупная и целая.
     
  9.  
  10. Device

    Device Активный пользователь

    С нами с:
    16 янв 2009
    Сообщения:
    28
    Симпатии:
    0
    Адрес:
    Саратов
    смысла не вижу например сумму в 25000 хранить в копейках, если один хрен при 2500000/100 = 25000.00 и при float(25000) = 25000.00. это решение помогло бы если я сумму каждого хранил в копейках так как они были бы в виде 1023,25252525 в бд если в рублях
     
  11. Ты умный. Делай как знаешь.
     
  12. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    Храню бабло в INT с точностью до 6 знака. бабло*1000000
     
  13. 440Hz, DECIMAL в принципе и есть INT, но с указуемой точностью.
     
  14. Device

    Device Активный пользователь

    С нами с:
    16 янв 2009
    Сообщения:
    28
    Симпатии:
    0
    Адрес:
    Саратов
    флоппик

    не катит, тоже самое
    то есть из

    25 //первый
    25 //второй
    25 //третий
    25 //четвертый
    0 //погрешность

    при изменении:

    16 //первый
    27.47 //второй
    27.47 //третий
    27.47 //четвертый
    1.59 //погрешность

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

    AlexGousev Активный пользователь

    С нами с:
    25 мар 2006
    Сообщения:
    1.505
    Симпатии:
    0
    Адрес:
    Москва
    Device
    Тут уже не раз обсуждали почему деньги нельзя хранить в float и double, поиском можно воспользоваться. Кратко: это неточное число. Т.е. float хранит не то значение, которое в него пишут, а примерное, приблизительное. Поэтому деньги хранят либо строкой (decimal) либо целым числом (int, bigint) с нужной точностью.
     
  17. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    при любых операциях деления в бабле есть погрешность. посему я бы завел еще один аккаунт и погрешность писал бы туда. тогда в сумме все было бы по нулям и общая сумма была бы всегда 100.

    p.s. Базилио, 5 на 2 не делиться? Получи свой золотой.
    гыгыгы
     
  18. karakh

    karakh Активный пользователь

    С нами с:
    11 дек 2007
    Сообщения:
    1.344
    Симпатии:
    0
    Угу. И завел бы этот аккаунт на свое имя :) И скорее всего влип бы, уж больно метода известна
     
  19. 440Hz

    440Hz Старожил
    Команда форума Модератор

    С нами с:
    21 дек 2012
    Сообщения:
    8.003
    Симпатии:
    1
    Адрес:
    Оттуда
    у меня системный акк. шеф в курсе. это его любимый аккаунт.
     
  20. armadillo

    armadillo Активный пользователь

    С нами с:
    6 апр 2007
    Сообщения:
    2.380
    Симпатии:
    0
    Адрес:
    Russia, Moscow
    вот обоих и посодютЪ. )))