php中浮点数计算问题整理

 更新时间:2016年11月25日 15:42  点击:2197
在php中浮点数计算通常我们会得不到自己想要的结果了,这个到底是什么原因呢,下面我们来分析问题的同时也给各位朋友整理了一些比较好用的实例。

如果用php的+-*/计算浮点数的时候,可能会遇到一些计算结果错误的问题,比如echo intval( 0.58*100 );会打印57,而不是58,这个其实是计算机底层二进制无法精确表示浮点数的一个bug,是跨语言的,我用python也遇到这个问题。所以基本上大部分语言都提供了精准计算的类库或函数库,比如php有BC高精确度函数库,下面达内php培训老师介绍一下一些常用的BC高精确度函数使用。

例子

 代码如下 复制代码
<?php    $f = 0.58;    var_dump(intval($f * 100)); //为啥输出57?>

为啥输出是57啊? PHP的bug么?

我相信有很多的同学有过这样的疑问, 因为光问我类似问题的人就很多, 更不用说bugs.php.net上经常有人问…

要搞明白这个原因, 首先我们要知道浮点数的表示(IEEE 754):

浮点数, 以64位的长度(双精度)为例, 会采用1位符号位(E), 11指数位(Q), 52位尾数(M)表示(一共64位).

符号位:最高位表示数据的正负,0表示正数,1表示负数。

指数位:表示数据以2为底的幂,指数采用偏移码表示

尾数:表示数据小数点后的有效数字.

这里的关键点就在于, 小数在二进制的表示, 关于小数如何用二进制表示, 大家可以百度一下, 我这里就不再赘述, 我们关键的要了解, 0.58 对于二进制表示来说, 是无限长的值(下面的数字省掉了隐含的1)..

0.58的二进制表示基本上(52位)是: 00101000111101011100001010001111010111000010100011110.57的二进制表示基本上(52位)是: 001000111101011100001010001111010111000010100011110而两者的二进制, 如果只是通过这52位计算的话,分别是:www.111cn.net

0.58 -> 0.579999999999999960.57 -> 0.5699999999999999至于0.58 * 100的具体浮点数乘法, 我们不考虑那么细, 有兴趣的可以看(Floating point), 我们就模糊的以心算来看… 0.58 * 100 = 57.999999999

那你intval一下, 自然就是57了….

可见, 这个问题的关键点就是: “你看似有穷的小数, 在计算机的二进制表示里却是无穷的”

so, 不要再以为这是PHP的bug了, 这就是这样的…..

PHP浮点型在进行+-*%/存在不准确的问题

例如:

1.<?php

$a = 0.1;
$b = 0.7;
var_dump(($a + $b) == 0.8);

打印出来的值为 boolean false
这是为啥?PHP手册对于浮点数有以下警告信息:
Warning
浮点数精度
显然简单的十进制分数如同 0.1 或 0.7 不能在不丢失一点点精度的情况下转换为内部二进制的格式。这就会造成混乱的结果:例如,floor((0.1+0.7)*10) 通常会返回 7 而不是预期中的 8,因为该结果内部的表示其实是类似 7.9999999999…。
这和一个事实有关,那就是不可能精确的用有限位数表达某些十进制分数。例如,十进制的 1/3 变成了 0.3333333. . .。
所以永远不要相信浮点数结果精确到了最后一位,也永远不要比较两个浮点数是否相等。如果确实需要更高的精度,应该使用任意精度数学函数或者 gmp 函数

 代码如下 复制代码

<?php

$a = 0.1;
$b = 0.7;
var_dump(bcadd($a,$b,2) == 0.8);

bcadd — 将两个高精度数字相加
bccomp — 比较两个高精度数字,返回-1, 0, 1
bcdiv — 将两个高精度数字相除
bcmod — 求高精度数字余数
bcmul — 将两个高精度数字相乘
bcpow — 求高精度数字乘方
bcpowmod — 求高精度数字乘方求模,数论里非常常用
bcscale — 配置默认小数点位数,相当于就是Linux bc中的”scale=”
bcsqrt — 求高精度数字平方根
bcsub — 将两个高精度数字相减

整理了一些实例

php BC高精确度函数库包含了:相加,比较,相除,相减,求余,相乘,n次方,配置默认小数点数目,求平方。这些函数在涉及到有关金钱计算时比较有用,比如电商的价格计算。
 

 代码如下 复制代码
/**
  * 两个高精度数比较
  *
  * @access global
  * @param float $left
  * @param float $right
  * @param int $scale 精确到的小数点位数
  *
  * @return int $left==$right 返回 0 | $left<$right 返回 -1 | $left>$right 返回 1
  */
var_dump(bccomp($left=4.45, $right=5.54, 2));
// -1
 
 /**
  * 两个高精度数相加
  *
  * @access global
  * @param float $left
  * @param float $right
  * @param int $scale 精确到的小数点位数
  *
  * @return string
  */
var_dump(bcadd($left=1.0321456, $right=0.0243456, 2));
//1.04
 
  /**
  * 两个高精度数相减
  *
  * @access global
  * @param float $left
  * @param float $right
  * @param int $scale 精确到的小数点位数
  *
  * @return string
  */
var_dump(bcsub($left=1.0321456, $right=3.0123456, 2));
//-1.98
 
 /**
  * 两个高精度数相除
  *
  * @access global
  * @param float $left
  * @param float $right
  * @param int $scale 精确到的小数点位数
  *
  * @return string
  */
var_dump(bcdiv($left=6, $right=5, 2));
//1.20
 
 /**
  * 两个高精度数相乘
  *
  * @access global
  * @param float $left
  * @param float $right
  * @param int $scale 精确到的小数点位数
  *
  * @return string
  */
var_dump(bcmul($left=3.1415926, $right=2.4569874566, 2));
//7.71
 
 /**
  * 设置bc函数的小数点位数
  *
  * @access global
  * @param int $scale 精确到的小数点位数
  *
  * @return void
  */
bcscale(3);
var_dump(bcdiv('105', '6.55957'));
// 16.007

 
注意点:关于设置的位数,超出部分是丢弃掉,而不是四舍五入。

今天在要php5.4.6中编译安装一个php-screw了,但是怎么操作都不成功了,后来看到有朋友博客写到一篇关于php-screw在php5.4.6上编译失败问题的解决方案,于是拿过来试了一下没想到还真解决了,下面我把文章拿出来与大家一起分享。

php-screw版本问题,报错

make

/bin/sh /root/php_screw-1.5/libtool --mode=compile cc -I. -I/root/php_screw-1.5 -DPHP_ATOM_INC -I/root/php_screw-1.5/include -I/root/php_screw-1.5/main -I/root/php_screw-1.5 -I/usr/include/php -I/usr/include/php/main -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /root/php_screw-1.5/php_screw.c -o php_screw.lo
libtool: compile: cc -I. -I/root/php_screw-1.5 -DPHP_ATOM_INC -I/root/php_screw-1.5/include -I/root/php_screw-1.5/main -I/root/php_screw-1.5 -I/usr/include/php -I/usr/include/php/main www.111cn.net -I/usr/include/php/TSRM -I/usr/include/php/Zend -I/usr/include/php/ext -I/usr/include/php/ext/date/lib -DHAVE_CONFIG_H -g -O2 -c /root/php_screw-1.5/php_screw.c -fPIC -DPIC -o .libs/php_screw.o
/root/php_screw-1.5/php_screw.c: In function ‘zm_startup_php_screw’:
/root/php_screw-1.5/php_screw.c:124: error: ‘struct _zend_compiler_globals’ has no member named ‘extended_info’
/root/php_screw-1.5/php_screw.c: In function ‘zm_shutdown_php_screw’:
/root/php_screw-1.5/php_screw.c:133: error: ‘struct _zend_compiler_globals’ has no member named ‘extended_info’
make: *** [php_screw.lo] Error 1

修改php-screw.c

 代码如下 复制代码


修改
CG(extended_info) = 1;

CG(compiler_options) |= ZEND_COMPILE_EXTENDED_INFO;

下面我整理了一些常用的数组转换成树的实例与大家一起学习,我想大家都会很喜欢这篇文章的哦。

Php代码 

 代码如下 复制代码
 
* $sourceArr 原来的数组
* $key 主键
* $parentKey 与主键关联的父主键
* $childrenKey 生成的孩子的键名
*
*/ 
 
function arrayToTree($sourceArr, $key, $parentKey, $childrenKey) 

    $tempSrcArr = array(); 
    foreach ($sourceArr as  $v) 
    { 
        $tempSrcArr[$v[$key]] = $v; 
    } 
    $i = 0; 
    $count = count($sourceArr); 
    for($i = ($count - 1); $i &gt;=0; $i--) 
    { 
        if (isset($tempSrcArr[$sourceArr[$i][$parentKey]])) 
        { 
           $tArr = array_pop($tempSrcArr); 
           $tempSrcArr[$tArr[$parentKey]][$childrenKey] = (isset($tempSrcArr[$tArr[$parentKey]][$childrenKey]) &amp;&amp; is_array($tempSrcArr[$tArr[$parentKey]][$childrenKey])) ? $tempSrcArr[$tArr[$parentKey]][$childrenKey] : array(); 
           array_push ($tempSrcArr[$tArr[$parentKey]][$childrenKey], $tArr); 
        } 
    } 
    return $tempSrcArr; 

 

 
Php代码 
 
 * 将数组转换成树
 * 例子:将 array(
            array('id'=>1,'parentId' => 0,'name'=> 'name1')
            ,array('id'=>2,'parentId' => 0,'name'=> 'name2')
            ,array('id'=>4,'parentId' => 1,'name'=> 'name1_4')
            ,array('id'=>15,'parentId' => 1,'name'=> 'name1_5')
    );转换成
 * Array(
    [1] => Array([id] => 1
            [parentId] => 0
            [name] => name1
            [children] => Array(
                    [0] => Array([id] => 15,[parentId] => 1,[name] => name1_5)
                    [1] => Array([id] => 4,[parentId] => 1,[name] => name1_4)
                )
        )
    [2] => Array([id] => 2,[parentId] => 0,[name] => name2)
)
 * @param array $sourceArr 要转换的数组
 * @param string $key 数组中确认父子的key,例子中为“id”
 * @param string $parentKey 数组中父key,例子中为“parentId”
 * @param type $childrenKey 要在树节点上索引子节点的key,例子中为“children”
 * @return array 返回生成的树
 */ 

 代码如下 复制代码
function arrayToTree($sourceArr, $key, $parentKey, $childrenKey) 

    $tempSrcArr = array(); 
 
    $allRoot = TRUE; 
    foreach ($sourceArr as  $v) 
    { 
        $isLeaf = TRUE; 
        foreach ($sourceArr as $cv ) 
        { 
            if (($v[$key]) != $cv[$key]) 
            { 
                if ($v[$key] == $cv[$parentKey]) 
                { 
                    $isLeaf = FALSE; 
                } 
                if ($v[$parentKey] == $cv[$key]) 
                { 
                    $allRoot = FALSE; 
                } 
            } 
        } 
        if ($isLeaf) 
        { 
            $leafArr[$v[$key]] = $v; 
        } 
        $tempSrcArr[$v[$key]] = $v; 
    } 
    if ($allRoot) 
    { 
        return $tempSrcArr; 
    } 
    else 
    { 
        unset($v, $cv, $sourceArr, $isLeaf); 
        foreach ($leafArr as  $v) 
        { 
            if (isset($tempSrcArr[$v[$parentKey]])) 
            { 
                $tempSrcArr[$v[$parentKey]][$childrenKey] = (isset($tempSrcArr[$v[$parentKey]][$childrenKey]) && is_array($tempSrcArr[$v[$parentKey]][$childrenKey])) ? $tempSrcArr[$v[$parentKey]][$childrenKey] : array(); 
                array_push ($tempSrcArr[$v[$parentKey]][$childrenKey], $v); 
                unset($tempSrcArr[$v[$key]]); 
            } 
        } 
        unset($v); 
        return arrayToTree($tempSrcArr, $key, $parentKey, $childrenKey); 
    } 

 

 
 
Php代码 
/**递归方法:**/ 
 
$rows = array( 
    0 => array('id' => 1, 'name' => '菜单1', 'parentId' => 0) 
    , 1 => array('id' => 2, 'name' => '菜单2', 'parentId' => 0) 
    , 2 => array('id' => 3, 'name' => '菜单3', 'parentId' => 0) 
    , 3 => array('id' => 4, 'name' => '菜单1_1', 'parentId' => 1) 
    , 4 => array('id' => 5, 'name' => '菜单1_2', 'parentId' => 1) 
    , 5 => array('id' => 6, 'name' => '菜单2_1', 'parentId' => 2) 
); 
print_r(getTree($rows, 0, 'id', 'parentId')); 

 代码如下 复制代码
 
/**
 * 数组根据父id生成树
 * @staticvar int $depth 递归深度
 * @param array $data 数组数据
 * @param integer $pid 父id的值
 * @param string $key id在$data数组中的键值
 * @param string $chrildKey 要生成的子的键值
 * @param string $pKey 父id在$data数组中的键值
 * @param int $maxDepth 最大递归深度,防止无限递归
 * @return array 重组后的数组
 */ 
function getTree($data, $pid = 0, $key = 'id', $pKey = 'parentId', $childKey = 'child', $maxDepth = 0){ 
    static $depth = 0; 
    $depth++; 
    if (intval($maxDepth) <= 0) 
    { 
        $maxDepth = count($data) * count($data); 
    } 
    if ($depth > $maxDepth) 
    { 
        exit("error recursion:max recursion depth {$maxDepth}"); 
    } 
    $tree = array(); 
    foreach ($data as $rk => $rv) 
    { 
        if ($rv[$pKey] == $pid) 
        { 
            $rv[$childKey] = getTree($data, $rv[$key], $key, $pKey, $childKey, $maxDepth); 
            $tree[] = $rv; 
        } 
    } 
    return $tree; 

一个实例

 代码如下 复制代码

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js"></script>
<title>TREE</title>
<style type="text/css">
/*树的全局CSS*/
.kyp_tree{
font: 12px/2.5 verdana;
float:left;display:inline;
}
.kyp_tree dd{
margin:0;padding:0;
margin-left:20px;
}
/*链接*/
.kyp_tree dl a{
font-size:12px;
color:#333;
text-decoration:none;
}
.kyp_tree dl a:hover, .kyp_tree dd dt.red_sub a{
font-size:12px;
color:#AE0002;
}
/*一级dl*/
.kyp_tree dl{
border-bottom:1px dashed #ccc;
margin:0;padding:0;
}
/*次级dl*/
.kyp_tree dl dl, .kyp_tree dl.last{
border:none;
}
.kyp_tree dd dt.currentClass{
background:url(tree_top.gif) no-repeat 0 -24px;
}
/*一级标题*/
.kyp_tree dt{
background:url(tree_top.gif) no-repeat 2px -57px;
padding-left:15px;
cursor:pointer;
font-size:13px;
height:30px;
line-height :27px;
line-height :32px9;
}
/*子标题*/
.kyp_tree dd dt{
background:url(tree_arrow.gif) no-repeat 2px 10px;
font-size:12px;
}
/*一级张开样式*/
.kyp_tree dt.open{
background:url(tree_top.gif) no-repeat 2px 12px;
}
/*张开样式*/
.kyp_tree dd dt.open{
background:url(tree_arrow.gif) no-repeat 0 -25px;
}
/*没有子节点的样式*/
.kyp_tree dt.nosub{
background:none;
}
</style>
<script type="text/javascript">
//<![CDATA[
jQuery.fn.createTree = function (fn, ini){
var $ = jQuery, ini = Object(ini);
this.find('dd').hide();
this.children('dl:last').addClass('last');
this.find('dt', this).each(function (){
var nosub = $(this).next('dd').size() == 0;
if (nosub) {
$(this).addClass('nosub');
}
if (ini.id && ini.id == $(this).attr('classify')) {
$(this).parents('dd').show().prev('dt').addClass('open');
$(this).addClass('red_sub');
if (nosub) {
$(this).addClass('currentClass')
}else{
$(this).next('dd').show();
$(this).addClass('open')
}
}
}).click(function (e){
var dd = $(this).next('dd'),
isClose = dd.css('display') == 'none';
if (dd.size()) {
if (isClose) {
dd.show();
$(this).addClass('open')
}else{
dd.hide();
$(this).removeClass('open')
}
}
return fn && fn.call(this, e, dd)
});
if (ini.mx) {
this.find('dt').click(function (e){
var J = $(this);
if (J.next('dd').size()) {
if (J.hasClass('open')) {
J.parent().siblings('dl').children('dd').hide();
J.parent().siblings('dl').children('dt').removeClass('open');
J.next('dd').show();
J.addClass('open')
}
}
})
}
};
(function ($){
$(function (){
$('#tree_wrap').createTree(function (e, dd){//回调(事件, 下一个dd)
$('#show').html(this.innerHTML+dd.size())
}, {mx: 1, id: 200})// mx是否互斥, id 当前类别
});
})(jQuery)
//]]>
</script>
</head>
<body>

<?php

// 树组的顺序即是分类的顺序,因此前当分类的下级子类一定要紧随其后
$tree= array(
1 => array('id'=>1, 'cname'=>'一级分类', 'pid'=>0),

100 => array('id'=>100, 'cname'=>'特意加进去的二级分类', 'pid'=>1),
101 => array('id'=>101, 'cname'=>'特意加进去的二级分类2222222222', 'pid'=>1),

2 => array('id'=>2, 'cname'=>'二级分类', 'pid'=>1),
3 => array('id'=>3, 'cname'=>'三级分类', 'pid'=>2),
4 => array('id'=>4, 'cname'=>'四级分类', 'pid'=>3),
5 => array('id'=>5, 'cname'=>'四级分类2', 'pid'=>3),
200 => array('id'=>200, 'cname'=>'55555', 'pid'=>5),
6 => array('id'=>6, 'cname'=>'另一级分类', 'pid'=>0),
7 => array('id'=>7, 'cname'=>'First First First', 'pid'=>0),
8 => array('id'=>8, 'cname'=>'First First First', 'pid'=>7),
);

// 指定分类ID,返回子类量(不进行深度递归)
function getChildTotal($id)
{
global $tree;
$total = 0;
foreach($tree as $value)
{
if ($id == $value['pid'])
{
$total++;
}
}
return $total;
}

 

// 指定分类ID,www.111cn.net并返回数组(不进行深度递归)
function getChildArray($id)
{
global $tree;
$array = array();
foreach($tree as $key=>$value)
{
if ($id == $value['pid'])
{
$array[$key] = $value;
}
}
return $array;
}


// 递归查询方式将树数组转换成HTML嵌套树

function getTreeHTML($tree,$level = 0)
{
if ($tree)
{
$level += 1;
foreach($tree as $id => $node)
{
$html .= "<dl>";
$html .= '<dt classify="'.$node['id'].'"><a href="http://www.baidu.com/">'.$node['cname']."</a></dt>";
if (getChildTotal($node['id']))
{
$tree_last = getChildArray($node['id']);

$html .= '<dd>';
$html .= getTreeHTML($tree_last,$level);
$html .= '</dd>';

}
$html .= '</dl>';
}
}
return $html;
}

$html = getTreeHTML( getChildArray(0) );
echo '<div id="tree_wrap" class="kyp_tree">';
echo $html;
echo '</div><div id="show" style="clear:both;border-top:1px solid red"></div>';

?>
</body>
</html>

时间戳是我们在时间日期对比时常用到一个小功能,下面我先来给各位介绍strtotime时间戳转换的一些方法与利用它来做一个日期格式化的几分钟、几小时前、几天前的一个实例。

1.PHP时间戳函数将日期转化为unix时间戳

世界末日时间戳 PHP

 代码如下 复制代码

echo "世界末日时间戳为:".strtotime("2012-12-21")


2.将时间戳转化为系统时间

 代码如下 复制代码


date('Y-m-d H:i:s',"1228348800");

3.PHP时间戳函数获取英文文本日期时间 示例如下:

便于比较,使用date将当时间戳与指定时间戳转换成系统时间

(1)打印明天此时的时间戳strtotime(”+1 day”)

 代码如下 复制代码

//当前时间
echo date("Y-m-d H:i:s",time());
//明天此时时间
echo date("Y-m-d H:i:s",strtotime("+1 day"));


(2)打印昨天此时的时间戳strtotime(”-1 day”)

 代码如下 复制代码

//当前时间
echo date("Y-m-d H:i:s",time()) ;
//指定时间
echo date("Y-m-d H:i:s",strtotime("-1 day"));


(3)打印下个星期此时的时间戳strtotime("+1 week")

 代码如下 复制代码


//当前时间
echo date("Y-m-d H:i:s",time());
//下星期时间
echo date("Y-m-d H:i:s",strtotime("+1 week"));


(4)打印上个星期此时的时间戳strtotime("-1 week")

 代码如下 复制代码

//当前时间
echo date("Y-m-d H:i:s",time());
//上个星期此时时间
echo date("Y-m-d H:i:s",strtotime("-1 week"));


(5)打印指定下星期几的时间戳strtotime("next Thursday")

 

 代码如下 复制代码
//当前时间
echo date("Y-m-d H:i:s",time());
//下星期几时间
echo date("Y-m-d H:i:s",strtotime("next Thursday"));


(6)打印指定上星期几的时间戳strtotime(”last Thursday”)

 代码如下 复制代码

//当前时间
echo date("Y-m-d H:i:s",time());
//指定时间
echo date("Y-m-d H:i:s",strtotime("last Thursday"));


以上PHP时间戳函数示例可知,strtotime能将任何英文文本的日期时间描述解析为Unix时间戳,我们结合mktime()或date()格式化日期时间获取指定的时间戳,实现所需要的日期时间

话说看到别人写的这么一个函数,测试了一下,有些小毛病:对于跨年日期,没有显示年份。修改如下

 代码如下 复制代码

function mdate($time = NULL) {
    $text = '';
    $time = $time === NULL || $time > time() ? time() : intval($time);
    $t = time() - $time; //时间差 (秒)
    $y = date('Y', $time)-date('Y', time());//是否跨年
    switch($t){
     case $t == 0:
       $text = '刚刚';
       break;
     case $t < 60:
      $text = $t . '秒前'; // 一分钟内
      break;
     case $t < 60 * 60:
      $text = floor($t / 60) . '分钟前'; //一小时内
      break;
     case $t < 60 * 60 * 24:
      $text = floor($t / (60 * 60)) . '小时前'; // 一天内
      break;
     case $t < 60 * 60 * 24 * 3:
      $text = floor($time/(60*60*24)) ==1 ?'昨天 ' . date('H:i', $time) : '前天 ' . date('H:i', $time) ; //昨天和前天
      break;
     case $t < 60 * 60 * 24 * 30:
      $text = date('m月d日 H:i', $time); //一个月内
      break;
     case $t < 60 * 60 * 24 * 365&&$y==0:
      $text = date('m月d日', $time); //一年内
      break;
     default:
      $text = date('Y年m月d日', $time); //一年以前
      break;
    }
       
    return $text;
}

ThinkPHP中:

将写好的函数放到 Common 文件夹下。系统会自动加载的。
放到这个common.php页里,common.php 固有格式,不要改名。

模板中直接调用

 代码如下 复制代码

{$vo.time|mdate}

例2,简单一些的

 代码如下 复制代码

function formatDate($sTime) {
 //sTime=源时间,cTime=当前时间,dTime=时间差
 $cTime  = time();
 $dTime  = $cTime - $sTime;
 $dDay  = intval(date("Ymd",$cTime)) - intval(date("Ymd",$sTime));
 $dYear  = intval(date("Y",$cTime)) - intval(date("Y",$sTime));
 if( $dTime < 60 ){
  $dTime =  $dTime."秒前";
 }elseif( $dTime < 3600 ){
  $dTime =  intval($dTime/60)."分钟前";
 }elseif( $dTime >= 3600 && $dDay == 0  ){
  $dTime =  "今天".date("H:i",$sTime);
 }elseif($dYear==0){
  $dTime =  date("m-d H:i",$sTime);
 }else{
  $dTime =  date("Y-m-d H:i",$sTime);
 }
 return $dTime;
}

 

cookie和session最大的区别一个是保存在服务器上,一个是保存在客户端电脑中,cookie安全性不如session而session用多了会占机器资源。

1、cookie数据存放在客户的浏览器上,session数据放在服务器上。

2、cookie不是很安全,别人可以分析存放在本地的COOKIE并进行COOKIE欺骗,考虑到安全应当使用session。

3、session会在一定时间内保存在服务器上。当访问增多,会比较占用你服务器的性能, 考虑到减轻服务器性能方面,应当使用COOKIE。

4、单个cookie在客户端的限制是3K,就是说一个站点在客户端存放的COOKIE不能3K。

例,COOKIE

如:setCookie('user','zhangsan',time()+3600),代表 user变量值为张三的cookie存活时间为1小时,在此要注意此函数属于头函数,也就相当于php中的header()跳转函数,在它之前不能有“任何输出(包括空格)”。
2、用$_COOKIE['user']来获取cookie值。www.111cn.net
3、注销cookie :setCookie('user','',time()-3600); 或 setCookie('user');
4、

//删除客户端在cookie中的sessionid
if(isset($_COOKIE[session_name()])){
           setCookie(session_name(),'',time()-30,'/');
}


例,session

1、//开启session
     session_start();
2、//清空session值
     $_SESSION = array();

//彻底销毁session
session_destroy();


session和cookie谁更安全 www.111cn.net

就个人而言,我觉得session更安全一点,我以下几点看法。

1,如果session和cookie一样安全的话,二者就没有并要同时存在了,只要cookie就好了,让客户端来分提服务器的负担,并且对于用户来说又是透明的。何乐而不为呢。

2,session的sessionID是放在cookie里,要想功破session的话,第一要功破cookie。功破cookie后,你要得到 sessionID,sessionID是要有人登录,或者启动session_start才会有,你不知道什么时候会有人登录。第二,sessionID是加密的,第二次session_start的时候,前一次的sessionID就没有用了,session过期时sessionid也会失效,想在短时间内功破加了密的 sessionID很难。session是针对某一次通信而言,会话结束session也就随着消失了,而真正的cookie存在于客户端硬盘上的一个文本文件,谁安全很显然了。

3,如果session这么容易被功破,这么不安全的话,我想现有的绝大部分网站都不安全了。

[!--infotagslink--]

相关文章

  • python 计算方位角实例(根据两点的坐标计算)

    今天小编就为大家分享一篇python 计算方位角实例(根据两点的坐标计算),具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...2020-04-27
  • PHP传值到不同页面的三种常见方式及php和html之间传值问题

    在项目开发中经常见到不同页面之间传值在web工作中,本篇文章给大家列出了三种常见的方式。接触PHP也有几个月了,本文总结一下这段日子中,在编程过程里常用的3种不同页面传值方法,希望可以给大家参考。有什么意见也希望大...2015-11-24
  • js修改input的type属性问题探讨

    js修改input的type属性有些限制。当input元素还未插入文档流之前,是可以修改它的值的,在ie和ff下都没问题。但如果input已经存在于页面,其type属性在ie下就成了只读属性了,不可以修改。...2013-10-19
  • Mysql常见问题集锦

    1,utf8_bin跟utf8_general_ci的区别 ci是 case insensitive, 即 "大小写不敏感", a 和 A 会在字符判断中会被当做一样的; bin 是二进制, a 和 A 会别区别对待. 例如你运行: SELECT * FROM table WHERE txt = 'a'...2013-10-04
  • Mysql大小写敏感的问题

    一、1 CREATE TABLE NAME(name VARCHAR(10)); 对这个表,缺省情况下,下面两个查询的结果是一样的:复制代码 代码如下: SELECT * FROM TABLE NAME WHERE name='clip'; SELECT * FROM TABLE NAME WH...2015-03-15
  • linux mint 下mysql中文支持问题

    一.mysql默认不支持中文,它的server和db默认是latin1编码.所以我们要将其改变为utf-8编码,因为utf-8包含了地球上大部分语言的二进制编码 1.关闭mysql服务 sudo /etc/init.d/mysql stop 2.修改mysql配置文件 mysql配...2015-10-21
  • JS实现购物车中商品总价计算

    这篇文章主要为大家详细介绍了JS实现购物车中商品总价的计算 ,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-03-07
  • go浮点数转字符串保留小数点后N位的完美解决方法

    这篇文章主要介绍了go浮点数转字符串保留小数点后N位解决办法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下...2020-05-11
  • C#使用队列(Queue)解决简单的并发问题

    这篇文章主要介绍了使用队列(Queue)解决简单的并发问题,讲解的很细致,喜欢的朋友们可以了解一下...2020-06-25
  • golang与php实现计算两个经纬度之间距离的方法

    这篇文章主要介绍了golang与php实现计算两个经纬度之间距离的方法,结合实例形式对比分析了Go语言与php进行经纬度计算的相关数学运算技巧,需要的朋友可以参考下...2016-07-29
  • PHP浮点数精度丢失问题解决方案

    浮点数就是有很我小数的那种并且不只单纯了数字了,而小编在用支付接口时就碰到浮点数丢失的问题,下文一起来看看问题解决方法. 先看下面这段代码: $f = 0.57; echo...2016-11-25
  • windows 10 安装和使用中5个常见问题

    2015年7月29日0点起,Windows 10推送全面开启,Windows7、Windows8.1用户可以免费升级到Windows 10,用户也可以通过系统升级到Windows10,在这过程中,用户会遇到这样那样的问题,下面小编总结了windows 10 安装和使用中5个常见问题,需要的朋友可以参考下...2016-01-27
  • C#实现计算一个点围绕另一个点旋转指定弧度后坐标值的方法

    这篇文章主要介绍了C#实现计算一个点围绕另一个点旋转指定弧度后坐标值的方法,涉及C#针对坐标的数学运算相关技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-06-25
  • php中session常见问题分析

    PHP的session功能,一直为许多的初学者为难。就连有些老手,有时都被搞得莫名其妙。本文,将这些问题,做一个简单的汇总,以便大家查阅。 1. 错误提示 引用 代...2016-11-25
  • c# 计算时间间隔的简单方法(推荐)

    下面小编就为大家带来一篇c# 计算时间间隔的简单方法(推荐)。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧...2020-06-25
  • javascript学习指南之回调问题

    回调函数被认为是一种高级函数,一种被作为参数传递给另一个函数(在这称作"otherFunction")的高级函数,回调函数会在otherFunction内被调用(或执行)。回调函数的本质是一种模式(一种解决常见问题的模式),因此回调函数也被称为回调模式。...2016-04-25
  • C语言简单实现计算字符个数的方法

    这篇文章主要介绍了C语言简单实现计算字符个数的方法,涉及C语言针对字符串的简单遍历与判定技巧,具有一定参考借鉴价值,需要的朋友可以参考下...2020-04-25
  • json error: Use of overloaded operator [] is ambiguous错误的解决方法

    今天小编就为大家分享一篇关于json error: Use of overloaded operator [] is ambiguous错误的解决方法,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧...2020-04-25
  • Vue如何使用Dayjs计算常用日期详解

    这篇文章主要给大家介绍了关于Vue如何使用Dayjs计算常用日期的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧...2021-03-09
  • Unity实现汽车前后轮倒车轨迹计算

    这篇文章主要为大家详细介绍了Unity实现汽车前后轮倒车轨迹计算,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...2021-09-13