Mysql PHP 7 , Strict Types, PDO MySQL и DECIMAL

Активист

Активист
Команда форума
Собственно невиданно для себя увидил, что decimal есть string!

Это бага или фича или еще не допилили?;)

PHP:
<?php
declare(strict_types=1);

/*

create database `php7` default charset 'utf8';

    use `php7`;

create table `types` (
  `id` int unsigned not null primary key,
  `signed_int` int signed,
  `unsigned_int` int unsigned,
  `signed_float` float signed,
  `unsigned_float` float unsigned,
  `signed_decimal` decimal(10,2) signed,
  `unsigned_decimal` decimal(10,2) unsigned
  );
insert into
  `types`
  (`id`, `signed_int`, `unsigned_int`, `signed_float`, `unsigned_float`, `signed_decimal`, `unsigned_decimal`)
values
  ('1', '-30', '44', '-300.33', '334.00033', '-324.34', '64.23')
; 
*/


$dbh = new PDO( "mysql:host=localhost;dbname=php7;unix_socket=/var/run/mysqld/mysqld.sock", "root" );
$dbh->setAttribute(PDO::MYSQL_ATTR_DIRECT_QUERY, false);
$sth = $dbh->prepare("select * from `types`");
$sth->execute();

$row = $sth->fetchObject("stdClass");


print "Type of `id`:" . gettype( $row->id ) . "\n";
print "Type of `signed_int`:" . gettype( $row->signed_int )  . "\n";
print "Type of `unsigned_int`:" . gettype( $row->unsigned_int )  . "\n";
print "Type of `signed_float`:" . gettype( $row->signed_float )  . "\n";
print "Type of `unsigned_float`:" . gettype( $row->unsigned_float )  . "\n";
print "Type of `signed_decimal`:" . gettype( $row->signed_decimal )  . "\n";
print "Type of `unsigned_decimal`:" . gettype( $row->unsigned_decimal )  . "\n";
Код:
keeper@keeper:/var/www/php7.localhost/httpdocs$ /opt/php/php-7.0 ./index.php 
Type of `id`:integer
Type of `signed_int`:integer
Type of `unsigned_int`:integer
Type of `signed_float`:double
Type of `unsigned_float`:double
Type of `signed_decimal`:string
Type of `unsigned_decimal`:string
 

флоппик

promotor fidei
Команда форума
Партнер клуба
А чем ему быть еще? Он целочисленный с точкой. Его нельзя ни во флоат, ни в инт без потерь.
 

Активист

Активист
Команда форума
Уж точно не строкой. В MySQL этот тип отнесен к численным типам. То и в PHP он должен быть типа float

О каких потерях речь?

Код:
keeper@keeper:/var/www/php7.localhost/httpdocs$ /opt/php/php-7.0  -a
Interactive mode enabled
<?php
var_dump( (float)"222.44" );
?>
float(222.44)
keeper@keeper:/var/www/php7.localhost/httpdocs$
 
Последнее редактирование:

флоппик

promotor fidei
Команда форума
Партнер клуба
Не понимаю, что в слове «целочисленное» тебя наталкивает на мысль, что это должен быть флоат. Над флоатом нельзя совершать математические операции без потери точности, и у децимала мантисса может быть больше, чем доступна у флоата, например.Именно поэтому для денег нужен decimal, который целочисленный.
 
Последнее редактирование:

Активист

Активист
Команда форума
Не понимаю, что в слове «целочисленное» тебя наталкивает на мысль, что это должен быть флоат. Над флоатом нельзя совершать математические операции без потери точности, и у децимала мантисса может быть больше, чем доступна у флоата, например.Именно поэтому для денег нужен decimal, который целочисленный.
@@@ь,
1. При выполнении операций в PHP после выборки $row->signed_decimal - $row->unsigned_decimal - они будут приведены к типу float.
2. Где вы в математике видели "Он целочисленный с точкой". Он число с плавающей точкой. Как он хранится в MySQL не имеет к выборки никакого значения. На выходе мы получаем float, а не строку. Тогда к четру весь этот type hinting, если из базы будет приходиться строка блять, когда там все множество чисел, а не строка. А сам MySQL относит их к числовым типам.
 

Фанат

oncle terrible
Команда форума
Активист.
Задай себе только один вопрос.
На какого хрена в базе отдельный тип децимал? И если его автоматически транслировать во флоат, то какой смысл иеть в базе два одинаковых типа?
 
Последнее редактирование:

Вурдалак

Продвинутый новичок

Redjik

Джедай-мастер
MySQL 5.7 stores DECIMAL values in binary format. See Section 12.19, “Precision Math”.
и как бе PDO приводит типы сам вроде, из мускула все строкой приходит (или я ошибаюсь?)

так что я не понимаю причин бомбежки... ну нет в php precision numeric type, вот и приводит пдо к такому типу, чтобы не потерять значение
 

Активист

Активист
Команда форума
Активист.
Задай себе только один вопрос.
На какого хрена в базе отдельный тип децимал? И если его автоматически транслировать во флоат, то какой смысл иеть в базе два одинаковых типа?
Он возвращаться из MySQLnd должен как float! Это не строка.
 

Фанат

oncle terrible
Команда форума
короче.
если тебе надо, чтобы возвращался флоат - храни как флоат.
А если не понимаешь, зачем нужен децел - просто не используй его.
 

Активист

Активист
Команда форума
Вы тесты видели? Выше. Поле INT он возвращает как INT, поле FLOAT как DOUBLE, а вот ЧИСЛОВОЙ ТИП DECIMAL как строку. Это числовой тип!
 

AnrDaemon

Продвинутый новичок
Да, это числовой тип. Попей водички, успокойся. А потом вспомни, что 0,1 десятичной системы невозможно представить в двоичной без потери точности.
 

WMix

герр M:)ller
Партнер клуба
избавляться надо от децималов и работать с int, нет это конечно классный тип, по в обычных языках такого типа не существует.
и если уже представлять его в пхп то нужен object типа
PHP:
class Decimal{
  public /*int */ $value;
  public /*int */ $scale;
}
и то я забыл про precision
 

MiksIr

miksir@home:~$
Вот странно такое увидеть тут. Decimal как тип создался именно для тех чисел, которые нельзя хранить во float. По-этому он и не переводится во float. Очевидно.
 
Сверху