9个小细节帮你优化CSS代码

前言:

网站加载缓慢,除了后端、JS与CDN背锅外,CSS也有可能是其中之一。虽然影响性质可能小于前面几位大佬,但是为了提高整体体验,还是很有必要了解的。

1.减少不必要的高消耗属性box-shadowborder-radiusposition: fixedtransform:nth-childfilter

上述几个CSS属性对性能要求相对较高。单页面少数使用不会产生影响。

当单页面罗列大量数据(几百条),且均涉及到上述部分样式,整体CSS渲染压力就会产生较为明显的差异,所以建议针对场景谨慎使用。

2.减少重复样式代码

多个元素或选择器需要相同CSS属性时,建议通过逗号组合相关选择器统一声明样式,避免单独重复声明。

优化前:

.header {
    color:#6d6d6d;
    margin: 10px 0;
    text-align: center;
}
.footer {
    color:#6d6d6d;
    margin: 10px 0;
    text-align: center;
}

优化后:

.header, .footer {
    color:#6d6d6d;
    margin: 10px 0;
    text-align: center;
}

3.简化选择器

设置HTML元素的方法有很多种,复杂的CSS选择器可以有多层级,但是这往往也会增加解析的耗时。降低选择器的复杂度可以减少浏览器解析的负载同时也能增加代码简洁增加可读性。当然也可以结合实际场景进行判断需求。

优化前:

.header>div.header-navigation ul li .option {
    color:#6d6d6d;
    text-align: center;
}

优化后:

.header .option {
    color:#6d6d6d;
    text-align: center;
}

4.避免使用 !important

当HTML元素存在多个重叠的样式时,除非不得不用,尽量避免通过 !Important 提升某一个样式的优先级。

添加 !Important CSS声明将覆盖掉其他对应的样式声明,如果CSS的规则中 !Important 太多,浏览器就必须对代码进行额外的检查,这可能会降低页面的加载速度。所以,尽量避免使用 !Important 。在很多情况下我们是可以通过选择器来实现样式重写的,除非是想要对第三方库的CSS进行重写。

5.使用CSS特效与SVG替代图片

图片资源相对较大,需要更多的加载时长,页面大量使用图片容易增加页面渲染的负担,虽然现阶段CDN、OSS等技术可以极大程度降低图片的渲染负载,但是还是把需求留给刚需吧,类似渐变、几何图形、边框、按钮等效果可以尽量使用CSS样式实现,甚至也可以使用SVG来替代PNG或者JPG图片。

6.压缩CSS

通过压缩CSS可以减少CSS文件中不必要的空白与换行从而减少文件大小。提升CSS的加载效率,降低加载时长。

7.使用0替换0px

当属性值为0是可以忽略单位。

写单位是没错的,只是当大型CSS文件中,往往存在较多属性值0的样式,忽略单位也可以减少一定的文件大小。

优化前:

.header {
    margin: 10px 0px 10px 0px;
}

优化后:

.header {
    margin: 10px 0;
}

8.尽量使用十六进制来指定颜色

设置颜色色值时使用颜色名称,浏览器需要额外消耗进行识别名称对应的十六进制,同时不同的浏览器识别的效果可能也存在差异,因此使用十六进制可以更精准,也更减少浏览器消耗。

优化前:

.header {
    color: red;
}

优化后:

.header {
    color: #ff0000;
}

9.使用 link 代替 @import

@import 规则主要用于导入资源或者CSS文件。它会阻止其他文件并行下载,并可能会导致网站速度变慢。

在HTML中用 标签代替 @import,可以并行加载CSS文件,避免等待。

优化前:

@import url("header.css");
@import url("slider.css");
@import url("content.css");
@import url("footer.css");

优化后:




嵌入式系统中浮点数累加问题

1 背景

一款流量计量产品,涉及到浮点数的累加,由于当时对浮点数的格式没有深入了解,想当然的就直接累加了。程序编制完毕,在调试时发现下列问题:瞬时量测量精度高于指标要求,累积量在程序运行的开始阶段精度也满足要求,但随着测量时间的增长,累积量的实际测量值和理论计算值之间的差别越来越大,超过了技术指标的要求。若不加干涉任其运行,当时间足够长时,显示模块显示的数据不再发生变化,即流量计的累积量不再发生变化了,但此时瞬时量显示的数据依旧正确。

表1 累积量测试结果

序号

累加初值

累加终值

实际累加值

误差

321

920

599

-0.17%

932

1524

592

-1.33%

1633

2223

590

-1.67%

2956

3537

581

-3.17%

某次测试时,通过设置流量计参数,使瞬时量理论值3600t/h,以10min为一个测量周期进行测量,理论计算得累积量每个周期应累加600。实测数据如表1所列。由表1中的数据可知,第1个测试周期精度满足要求,从第2个周期开始误差已经超过了技术指标要求,并且误差随着时间的增加而增大,在这种状态下流量积算仪是无法正常工作的。为什么会出现这种累加误差呢?要解决这个问题我们就有必要先了解一下浮点数的定义及在内存中存储格式。

2 浮点数的存储格式

实数r的二进制科学计数法可表示为r=(- 1)S×2E× M, 其中 S ( Sign)为实数的符号, “0”正 “1”负。E ( Exponent ) 为二进制数的指数, M( Mantissa)表示尾数,规范的二进制数 M = 1. d1d2 …dN C 语言的浮点数类型Float和Double采纳了IEEE 754标准中所定义的单精度32位浮点数和双精度64位浮点数的格式。具体的格式参见表 2和表3。

表中的指数域采用移码方式存储,单精度要指数值加上偏移量127,双精度要指数值加上偏移量1023。比如,单精度的实际指数值0在指数域中将保存为127;而保存在指数域中的64则表示实际的指数值-63。对于单精度数,可以表达的指数值的范围在-127~+128 之间(包含两端) 。实际的指数值-127(保存为全0)以及+128(保存为全1)保留用作特殊值的处理。这样,实际可以表达的有效指数范围就在-126~ +127之间。

表中的第三个域为尾数域,其中单精度数为23位长,双精度数为52位长。除了某些特殊值外,IEEE 标准要求浮点数必须是规范的。这意味着尾数的小数点左侧必须为1,因此在保存尾数的时候,可以省略小数点前面这个1,从而腾出一个二进制位来保存更多的尾数。这样实际上用23位长的尾数域表达了24位的尾数。

表2 单精度浮点数

符号

指数

尾数

1bit

8bit

23bit

表3 双精度浮点数

符号

指数

尾数

1bit

11bit

52bit

值得注意的是,对于单精度数,由于我们只有24位的尾数(其中一位隐藏) ,所以可以表达的最大尾数为224-1= 16777215。由此,我们可以看到单精度的浮点数可以表达的十进制数值中,真正有效的数字不高于8 位。 Float型的一些特殊约定:

1) 当E= 0,M= 0时,表示0;

2) 当E = 0,M!= 0时,表示非规范化数,即r= (-1) S×2-127×( 0. M) ;

3) 当E = 255,M= 0时,表示无穷大,用符号位来确定是正无穷大还是负无穷大;

4) 当E= 255, M! = 0时,表示 N aN (No t a Number,不是一个数);

对于Double型,也有相似的约定。

3 浮点数累加误差问题解决

通过对累积量测试结果的分析我们找到了产生误差的原因:程序中在计算累积量SUM时执行的是SUN=SUM+Instant,而参考文献明确告诉我们,两个浮点数相加时,其误差随着两个数差别的增大而增大。表1中误差的变化规律也证明了这一点。这是因为每次执行语句“SUM=SUM+Instant;”时,Instant是不变的,而SUM在不断增加。当两者大小相差的数量级足够大时,Instant与SUM相加会丢失Instant,致使流量计累积量读数不再发生变化,这也是前面调试时出现问题的原因。

为什么两个相差很大的浮点数相加会误差很大呢?通过上面对浮点数存储格式的分析可以知道,由于Float 型变量是用有限的存储单元存储的,因此能提供的有效数字总是有限的,在有效位以外的数字将被舍去,由此可能会产生一些误差。

例如:

Main( )

{ float a, b;

a=123456.789e5;

b=a+20.0f;

printf(“a=%f\n b=%f\n”,a ,b) ; }

运行结果:

a=12345678848.000000

b=12345678848.000000

输出结果是a与b相等。但理论上b应比a大20,应为12345678920。而Float型变量只能保证7位有效数字。后面的数字是无意义的,并不准确地表示该数。因此应该避免将一个很大的数和一个很小的数直接相加或相减,否则就会“丢失”小的数。

知道了以上原因,对于累积量的累加我们就有了应对措施。在程序中将累积量的变量分为整数部分和小数部分分别定义,即定义两个float型变量INT_SUM和FP_SUM。INT_SUM中只保存累积量的整数部分,而FP_SUM中保存累积量的小数部分。在进行流量的累积计算时执行“FP_SUM=FP_SUM+Instant;”当FP_SUM中的值大于等1.0时,INT_SUM=INT_SUM+1,同时FP_SUM=FP_SUM-1.0,这样FP_SUM中的值就始终是小于1的小数。因为INT_SUM=INT_SUM+1始终执行的是整数操作,不存在精度问题,而执行“FP_SUM=FP_SUM+Instant;”时FP_SUM是小于1的小数部分,Instan每秒也是小于等于1(最大量程是3600t/h)的数据,二者相加精度也是满足要求的。最终的累积量等于INT_SUM 与FP_SUM的和,显示时先求二者的和再进行显示。虽然在求INT_SUM 与FP_SUM的和时也存在误差,但误差不是累积的,不会随时间的推移而增大,并且FP_SUM只是小于1的小数部分,最终误差可以忽略不计。

采用上述方法对累积量进行处理后,很好地解决了测量精度随时间增加而变大的问题,最终使计量精度达到了供需双方都满意的范围。

4 C语言中浮点数使用时的几点建议

通过以上对C语言中浮点数存储格式的及实际应用中的问题分析,可以得出一下结论:

(1)避免将一个很大的浮点数和一个很小的浮点数数直接相加或相减

因为这样做可能会丢失小的数。特别是在累加计算时,由于初始时,基数很小可能看不出问题,但随着时间的推移,基数的增大,问题就出来了。这给程序的正常运行埋下了隐患。

(2)避免对两个浮点数直接做是否相等的判断

由于浮点数在内存中的存储误差,因此可能出现这样的情况:在理论上应该相等的两个数,用计算机却判断它们却为不相等。如果想判断x是否等于y ,应改写为:fabs(x-y)

(3)慎用浮点数作为循环变量

C语言中的循环变量可以用浮点数,但是使用浮点数作为循环变量一定要仔细考虑,由于浮点数的误差,可能会使循环次数达不到预定的次数而导致程序出现逻辑错误。

本站内容来自用户投稿,如果侵犯了您的权利,请与我们联系删除。联系邮箱:835971066@qq.com

本文链接:http://news.xiuzhanwang.com/post/2349.html

友情链接: