Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
MySQL 5. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В. PHP на примерах (2 издание). Авторы: Кузнецов М.В., Симдянов И.В. Программирование. Ступени успешной карьеры. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Не работает округление до сотых
 
 автор: tvv123456   (16.05.2010 в 19:34)   письмо автору
 
 

есть код:

<?
if(isset($_POST['ex']))
{

$dis='';
$error 0;
$sum round($_POST['sum'],2); //округляю
if(!preg_match("|^[0-9.]+$|",$sum) or $sum==0) {$error 1$dis .= "<br>-".$language[71];}

// Проверяем пришло ли с селекта то что нужно
   
switch($_POST['from'])
   {
case 
"WebMoney":
$from "WebMoney";
break;

case 
"PayPal":
$from "PayPal";
break;

case 
"Liberty_Reserve":
$from "Liberty_Reserve";
break;

case 
"PerfectMoney":
$from "PerfectMoney";
break;

case 
"Liqpay":
$from "Liqpay";
break;

case 
"Global_digital_pay":
$from "Global_digital_pay";
break;

default:
$from "0";
break;
    }
    
    
    
// Проверяем пришло ли с селекта то что нужно
switch($_POST['in'])
{
case 
"WebMoney":
$in "WebMoney";
break;

case 
"PayPal":
$in "PayPal";
break;

case 
"Liberty_Reserve":
$in "Liberty_Reserve";
break;

case 
"PerfectMoney":
$in "PerfectMoney";
break;

case 
"Liqpay":
$in "Liqpay";
break;

case 
"Global_digital_pay":
$in "Global_digital_pay";
break;

default:
$in "0";
break;
}

 
 if(
$myrowus[$from]<$sum || $from == "0") {$error 1$dis .= "<br>-".$language[88]." ".$from."(".$myrowus[$from]."$)".$sum;}
 if(
$in == "0") {$error 1$dis .= "<br>-".$language[134]." ".$in;}
 if(
$in == $from) {$error=1$dis .= "<br>-".$language[135];}

  if(
$error !=0) {echo "<font color=red><b>".$dis."</b></font>";}
  else
  {
$sum_pr $sum-$sum*($ex['kom']/100); //сумма обмена
  
$sum_pr round($sum_pr,2);//округляем результат до сотых
  
mysql_query("UPDATE users SET ".$from."=".$from."-$sum,".$in."=".$in."+$sum_pr WHERE 
id=
$id_user",$db) or die("Не прошел запрос к базе. Баланс не обновлен!"); //пишем в базу
  
echo "<head>
<meta http-equiv='Refresh' content='0; URL=exch.php'>


 </head>"
;

  }


}




Вроде все что нужно округлил до сотых но в базу пишеться значения типа 3,00000000001 . Тип поля VARCHAR

Не подскажите где ошбися?

  Ответить  
 
 автор: tvv123456   (16.05.2010 в 21:40)   письмо автору
 
   для: tvv123456   (16.05.2010 в 19:34)
 

Решил проблему поменяв тип поля в mysql на float(10,2)
Но если есть другие замечания рад выслушать :)

  Ответить  
 
 автор: Trianon   (21.05.2010 в 12:29)   письмо автору
 
   для: tvv123456   (16.05.2010 в 21:40)
 

DECIMAL а не FLOAT
DECIMAL с точностью, достаточной для хранения всех значащих цифр.

  Ответить  
 
 автор: cheops   (21.05.2010 в 09:48)   письмо автору
 
   для: tvv123456   (16.05.2010 в 19:34)
 

У вас эта ошибка округления скорее всего возникает уже на уровне MySQL - вы же вычисления осуществляете в SQL-запросе, в этом случае и округление нужно производить средствами MySQL, например, при помощи MySQL-функции ROUND().

  Ответить  
 
 автор: tvv123456   (22.05.2010 в 15:21)   письмо автору
 
   для: cheops   (21.05.2010 в 09:48)
 

Спасибо всем за советы. Очень признателен

  Ответить  
 
 автор: tvv123456   (23.05.2010 в 23:23)   письмо автору
 
   для: tvv123456   (22.05.2010 в 15:21)
 

Ладно я тут чуток лоханулся.
НО

давайте посмотрим: разве 0....1 в десятичной системе исчесления после сех много миллионых преобразований в двоичный код и обратно не должно остаться таким же числом 0......1?
Почему нужно учитывать нюансы работы php и СУБД mysql ? Почему нельзя всех овц подстричь под одну стрижку?

  Ответить  
 
 автор: Trianon   (24.05.2010 в 00:14)   письмо автору
 
   для: tvv123456   (23.05.2010 в 23:23)
 

Вы можете попросить отвесить в магазине ровно 1/3 кг картошки?

а меж тем в троичной системе счисления эта величина записывается с очень скромной точностью - в виде 0,1
всего один троичный разряд после точки.

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 00:26)   письмо автору
 
   для: Trianon   (24.05.2010 в 00:14)
 

Ну то есть вы хотите сказать что mysql и php работают в разных разрядах?
НУ вообше почему такая ошибка возникла? Я ее решил, но мне важно понять сам процесс и так далее

  Ответить  
 
 автор: cheops   (24.05.2010 в 00:31)   письмо автору
 
   для: tvv123456   (24.05.2010 в 00:26)
 

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

  Ответить  
 
 автор: cheops   (24.05.2010 в 00:28)   письмо автору
 
   для: tvv123456   (23.05.2010 в 23:23)
 

Нулями и единицами можно представить только целые числа, для дробных нужна уже модель, кроме того некоторые дроби периодические, т.е. их конечным числом с плавающей точкой вообще представить нельзя (Trianon выше привел 1/3 == 0.333(3)). Это даже уже не компьютерная, а алгебраическая проблема. На листе бумаге при работе с такими дробями тоже округлять придется. Ситуация осложняется тем, что числа с плавающей точкой в компьютере представлены в виде модели (любая модель весегда грубее объективной реальности), так как процессоры оперируют только целыми числами.

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 00:32)   письмо автору
 
   для: cheops   (24.05.2010 в 00:28)
 

-

  Ответить  
 
 автор: Trianon   (24.05.2010 в 00:44)   письмо автору
 
   для: tvv123456   (24.05.2010 в 00:32)
 

php держит данные либо в виде строк. Либо в виде чисел. Числа - только в двоичной системе.
MySQL тоже держит данные либо в виде строк либо в виде чисел.
Но числа может держать как в двоичной (FLOAT, INT) так и в десятичной (DECIMAL) системе.
При переходе от двоичной системы к десятичной и наоборот могут набегать ошибки округления.
Обусловлены они тем, что 10 не является целой степенью 2 .

К примеру, (дробные) числа по системам счисления (2, 4, 16, 256) ; (2, 8, 64 ); (3, 9; 81) ; могут бегать без искажений.
а выпрыгивая из степенного ряда оснований систем счисления - уже не могут.

Целые числа точно преобразуются куда угодно.

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

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 01:07)   письмо автору
 
   для: Trianon   (24.05.2010 в 00:44)
 

Trianon, мысль изреченная вами как всегда есть истинна, но у меня то в чем в(моем) коде была проблема(если не считать что я поляч на float перевел) varchar по диее должен сохранять все как есть еще круче чем text(надеюсь вы понлиииииии::)))))))))

  Ответить  
 
 автор: Trianon   (24.05.2010 в 01:20)   письмо автору
 
   для: tvv123456   (24.05.2010 в 01:07)
 

У Вас же там в SQL-коде арифметические операции задействованы были?
Какой нафиг варчар после них? Один только флоат. А он двоичен как из пушки.

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 01:50)   письмо автору
 
   для: Trianon   (24.05.2010 в 01:20)
 

дак блин сложно(по-моему) арифметически получить0,01+0,2 = 0,2145484845487487897987
А вы не находите?

  Ответить  
 
 автор: Trianon   (24.05.2010 в 01:53)   письмо автору
 
   для: tvv123456   (24.05.2010 в 01:50)
 

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

PS. 0.01 + 0.2 будет равно ... нулю. Если выполнять операцию в целых числах. Не удивляет ведь?

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 01:56)   письмо автору
 
   для: Trianon   (24.05.2010 в 01:53)
 

а куда сложнее - то? это же арифтметика. Глянте на мой изначальный код, там именно 0.1+2
И ЕМУ ПОДОБНОЕ, ВСЕ ОКРУГЛЯЕТЬСЯ, ТУТ ИМЕННО что мускул что-то выдает(все чилса округлены до сотых а она выдает миллионные? что за фигня вообще?

  Ответить  
 
 автор: Trianon   (24.05.2010 в 01:58)   письмо автору
 
   для: tvv123456   (24.05.2010 в 01:56)
 

Изначальный код?
SQL?
Не обнаружил.

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 02:02)   письмо автору
 
   для: Trianon   (24.05.2010 в 01:58)
 

UPDATE users SET users webmoney=webmoney+1 WHERE  
id=$id_user
устроит?
Вообщем то проблема не в этом
допустим 2+1=3 - кто поспорит?
Но почему то мускул по выше приведенному считает что это 3,00000000000000001 и это некрасиво вписываеться в дизайн

  Ответить  
 
 автор: Trianon   (24.05.2010 в 02:11)   письмо автору
 
   для: tvv123456   (24.05.2010 в 02:02)
 

следовательно это было 2.00000000000001 + 1 = 3.00000000000001
и извините, но это не то же самое, что 0,01+0,2 = 0,2145484845487487897987
Посчитали бы относительную погрешность. Она за пределами представимой точности. В отличие от.
А на дизайн мускул чихать хотел. И был где-то как-то прав.

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 02:14)   письмо автору
 
   для: Trianon   (24.05.2010 в 02:11)
 

Ну вы глянте на код то что я в начале( в первом посте) написал-то
я там на уровне php все округляю до сотых

Вообщем трабла(БЫЛА и ИМЕНно БЫЛА) в том что я на php ысе что можно кастрировал до сотых а в базу шло херь какая-та(тип поля варчар)

  Ответить  
 
 автор: Trianon   (24.05.2010 в 02:16)   письмо автору
 
   для: tvv123456   (24.05.2010 в 02:14)
 

повторяю еще раз.
SQL-кода с подставленными арифметическими величинами там нет.
Есть фрагменты текста на php до момента вызова.
Приводите оконечный SQL-код с дампом строк таблицы - будем разбираться.
А так - голословно всё.

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 02:19)   письмо автору
 
   для: Trianon   (24.05.2010 в 02:16)
 

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

А сумму он там пытался перевести 7 баксов(но говорю вам там всю даже при подсчтетах округляеться на уровне пхп а в мускул отдаеться арифметика)

Я УВЕРЕН ЧТО PHP ОТДАЕТ МУSQL ЧИСЛА ОКРУГЛЕННЫЕ ДО СОТЫХ, А МУСКУЛ УЖЕ НАЧИНАЕТ ВЫПЕНДРИВАТЬСЯ

  Ответить  
 
 автор: Trianon   (24.05.2010 в 03:43)   письмо автору
 
   для: tvv123456   (24.05.2010 в 02:19)
 

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

>Я УВЕРЕН ЧТО PHP ОТДАЕТ МУSQL ЧИСЛА ОКРУГЛЕННЫЕ ДО СОТЫХ, А МУСКУЛ УЖЕ НАЧИНАЕТ ВЫПЕНДРИВАТЬСЯ

php не умеет MySQL'у числа отдавать - только строки. И принимать только строки умеет.
И эти самые строки Вы и не приводите. Говорить не о чем.

  Ответить  
 
 автор: cheops   (24.05.2010 в 00:46)   письмо автору
 
   для: tvv123456   (24.05.2010 в 00:32)
 

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

  Ответить  
 
 автор: tvv123456   (24.05.2010 в 00:50)   письмо автору
 
   для: cheops   (24.05.2010 в 00:46)
 

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

  Ответить  
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования