V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
V2EX  ›  GeruzoniAnsasu  ›  全部回复第 145 页 / 共 148 页
回复总数  2950
1 ... 137  138  139  140  141  142  143  144  145  146 ... 148  
2017-12-19 17:07:04 +08:00
回复了 wisej 创建的主题 Python 十进制浮点数相乘问题
@wisej 首先再强调一次,你期望的“精确的 12.300 ”在浮点运算硬件中是无法存在的,在浮点寄存器中无法存放无法表示,想要精确表示 12.3000,只能有两种办法

1. 不采用浮点数,而用分数表示,也就是这个数就记录为 int(12)+int(3)/int(10)。注意这个方法还是可硬件实现的,只是没有这样的硬件而已。
2. 不采用硬件浮点运算单元,用软件模拟,以 10 进制小数习惯进行运算,4.10e0*3.0e0==1.23e1


第一种方法如果用硬件实现,表示一个数需要 3 部分存储单元而且无法表示无理数,除非为了些莫名其妙的目的专门造否则不可能做这样的硬件。如果软件模拟,则其实跟第二种方法差不多。

那么现在就只剩第二种方法了,软件模拟计算。

软件模拟!

都软件模拟了,还要多说吗?当年 8087 协处理器是用来干啥的,不就是解决 8086 算浮点太慢的问题嘛,没有任何一个现代 CPU 是不带浮点运算单元的,因为实在太重要。


“为什么会采用这种标准” 是一脉相承的,首先有了开关,然后有了二进制和晶体管,然后有了数字电路,然后有了集成电路和定点运算 cpu,然后有了浮点协处理器,然后才有了现代自带浮点单元的 CPU。整个计算机世界的所有标准都是从那个二进制开关传承下来的,如果人们发现的那个可以作为开关的三极管有三个可控稳定态,那么现在数字世界的编码方式很可能就是三进制的了

扯远了,总之你的问题,你以为的因果是 12.29999→数是以二进制表示的→无法精确;但实际上的因果关系是,数字电路必定是二进制的→IEEE 标准浮点→浮点运算器→你看到的结果。



“语言设计者为什么不内部进行处理返回我们所期望的值 12.3 呢” ← 所以,为了能产出不那么反直觉的结果,c/++在输出的时候做了额外处理,使其能重新还原成人们熟悉的小数结果,而 python 默认没这么做,而是另外提供 decimal 模块半软件半硬件地来以人类直觉 10 进制计算小数
2017-12-19 10:23:33 +08:00
回复了 wisej 创建的主题 Python 十进制浮点数相乘问题
@wisej c++里并不是 12.3 仍然是 12.299999,只是在输出的时候有些额外的 workaround


------------------------------------源码----------------------------------------
#include <stdio.h>
int flg = 0;
int main()
{
double v1 = 4.1;
double v2 = 3;
printf("%lf",v1*v2);
}
---------------------------------------------------------------------------------
----------------------------------编译结果------------------------------------

flg:
.zero 4
.LC2:
.string "%lf"
main:
push rbp
mov rbp, rsp
sub rsp, 16
movsd xmm0, QWORD PTR .LC0[rip]
movsd QWORD PTR [rbp-8], xmm0
movsd xmm0, QWORD PTR .LC1[rip]
movsd QWORD PTR [rbp-16], xmm0
movsd xmm0, QWORD PTR [rbp-8]
mulsd xmm0, QWORD PTR [rbp-16]
mov edi, OFFSET FLAT:.LC2
mov eax, 1
call printf
mov eax, 0
leave
ret
.LC0:
.long 1717986918
.long 1074816614
.LC1:
.long 0
.long 1074266112

(可以直接在 https://gcc.godbolt.org/实时查看代码段在不同编译器下的结果)




---------------------------------------GDB-----------------------------------------


[----------------------------------registers-----------------------------------]
RAX: 0x400526 (<main>: push rbp)
RBX: 0x0
RCX: 0x0
RDX: 0x7fffffffddc8 --> 0x7fffffffe1b6 ("XDG_SEAT=seat0")
RSI: 0x7fffffffddb8 --> 0x7fffffffe1ab ("/tmp/a.out")
RDI: 0x1
RBP: 0x7fffffffdcd0 --> 0x400570 (<__libc_csu_init>: push r15)
RSP: 0x7fffffffdcc0 --> 0x4008000000000000
RIP: 0x400552 (<main+44>: mov edi,0x4005f8)
R8 : 0x4005e0 (<__libc_csu_fini>: repz ret)
R9 : 0x7ffff7de7ab0 (<_dl_fini>: push rbp)
R10: 0x846
R11: 0x7ffff7a2d740 (<__libc_start_main>: push r14)
R12: 0x400430 (<_start>: xor ebp,ebp)
R13: 0x7fffffffddb0 --> 0x1
R14: 0x0
R15: 0x0
EFLAGS: 0x206 (carry PARITY adjust zero sign trap INTERRUPT direction overflow)
[-------------------------------------code-------------------------------------]
0x400543 <main+29>: movsd QWORD PTR [rbp-0x8],xmm0
0x400548 <main+34>: movsd xmm0,QWORD PTR [rbp-0x10]
0x40054d <main+39>: mulsd xmm0,QWORD PTR [rbp-0x8]
=> 0x400552 <main+44>: mov edi,0x4005f8
0x400557 <main+49>: mov eax,0x1
0x40055c <main+54>: call 0x400400 <printf@plt>
0x400561 <main+59>: mov eax,0x0
0x400566 <main+64>: leave
[------------------------------------stack-------------------------------------]
0000| 0x7fffffffdcc0 --> 0x4008000000000000
0008| 0x7fffffffdcc8 --> 0x4010666666666666
0016| 0x7fffffffdcd0 --> 0x400570 (<__libc_csu_init>: push r15)
0024| 0x7fffffffdcd8 --> 0x7ffff7a2d830 (<__libc_start_main+240>: mov edi,eax)
0032| 0x7fffffffdce0 --> 0x0
0040| 0x7fffffffdce8 --> 0x7fffffffddb8 --> 0x7fffffffe1ab ("/tmp/a.out")
0048| 0x7fffffffdcf0 --> 0x100000000
0056| 0x7fffffffdcf8 --> 0x400526 (<main>: push rbp)
[------------------------------------------------------------------------------]
Legend: code, data, rodata, value
0x0000000000400552 in main ()
gdb-peda$ p $xmm0
$1 = {
v4_float = {-1.58818668e-23, 2.63437486, 0, 0},
v2_double = {12.299999999999999, 0},
v16_int8 = {0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0x28, 0x40, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0},
v8_int16 = {0x9999, 0x9999, 0x9999, 0x4028, 0x0, 0x0, 0x0, 0x0},
v4_int32 = {0x99999999, 0x40289999, 0x0, 0x0},
v2_int64 = {0x4028999999999999, 0x0},
uint128 = 0x00000000000000004028999999999999
}
gdb-peda$


可以很清楚地看到算出来就是 12.29999999999999,这是机器码已经决定了的。只是在 printf 后被%lf 重新格式化成了 12.300000
2017-12-19 10:10:05 +08:00
回复了 biocom 创建的主题 程序员 有一个问答产品的 idea,大家觉得有没有可行性
用户自发驱动的内容有相当的不确定性,是一定没法只用某种单一官方的激励去达到期望场景的,期望有大部分能用户观众能充当裁判身份是不靠谱的,观众本身是最大的噪音来源,他们不产生内容,会被莫名其妙的东西引导,会有(特别在问答社区)严重的盲目性,所以别想着什么都能有第三方监督,三方监督只在观众-题主-回答三个身份都相互独立无法相互干扰的情况下成立,这也是技术性问答社区容易立足,而知乎这种泛问答平台充斥大量垃圾节奏问题的原因
2017-12-19 09:59:18 +08:00
回复了 biocom 创建的主题 程序员 有一个问答产品的 idea,大家觉得有没有可行性
就本帖来说

1. 题主肯为这个问题付 8 块钱吗
2. 有人愿意为了抢这 8 块钱写个 2k 字去详细分析下这个产品方案可不可行吗?反正我肯定不会,专业分析几千字我按 1 字 1 块收还差不多
3. 前面已经有个傻帽闲得慌已经写了 1k 字了但都是错的偏偏他还是个大 v 一堆人点赞你咋办,我选择离开
4. 题主的问题在今天内得到了解决,大家一致认定能成,于是题主随便选了个稍微字多的比如我然后把钱分了,但是 5 年后大家验证后发现这个方案扑街,然后一堆人重新反对+没有帮助,得,那我这 8 块钱还退回去?怎么退?不退了? 5 年后人家有实践告诉大家真的不可行了,赞同比我这个回答多一倍,然后反而还是我拿钱???
5.0. 问题:这个语言特性是怎么实现的?(悬赏 30 ) 回答 1:我也不知道(赞同 10 )
5.1. 问题:这个语言特性是怎么实现的?(悬赏 30 ) 回答 100:(赞同 1 赞同 2 赞同 1 3 0 0 0 1 0 0 0 ......)
5.2. 上边这俩问题怎么结算?

其它问题

6. 首页-热门回答-第一条:身材非常好是一种什么体验(悬赏 100 ),3k 回答,赏金分了前十。第二条:你家的猫颜值有多高(悬赏 8 ),3k 回答,得分答案:题主先自己来放一张吧 balabala (赞 1k ),第二答案:balabala (赞 996 )
@whwq2012 电热器哪有功率小的,2kw,开半小时一度电
1. 大神早都过了做作业的阶段,家教辅导小学生写作业还要钱呢 lz 你……
2. wireshark
3. 作业要么抄要么做,抄你同学的就行复制粘贴 refactor 改改变量名提交就行跑这里伸手,噗嗤
4. qt 是个用 c++/qml/js 开发的库,C 语言是行不通的,第一行就行不通谢谢
2017-12-15 15:38:34 +08:00
回复了 wisej 创建的主题 Python 十进制浮点数相乘问题
“正确结果”这个说法本来就很模糊
1/3=0.33333333...是正确的
1.2*3.0=5.9999999...也是正确的

不管是定点还是浮点,用小数来表示除不尽的分数怎样都会丢失精度,所以在涉及浮点的运算从来都是判断结果是否小于最小精度目标的,这应该是常识

用 decimal 模块只是以 10 进制的习惯思路去计算而已,你看习惯了 0.33333 自然不觉得有什么问题,但实际上十进制 if(1/3==0.3) 和二进制 if(1.2*3==3.6)差不多是一回事
2017-12-15 15:31:23 +08:00
回复了 johncang 创建的主题 问与答 火山小视频极限咏宁摔死了
知乎一句话终结评价

没有哪个极限运动爱好者是做完两个引体向上就没力气了的
“哎这单车我们要运回去维修了啊”
“哎这单车上咋还有辆奔驰,谁的奔驰忘了,算了估计是不要了”
@predator 熟悉系统跟干活本来就是两回事 lin/win user 跟 是不是码农本来也没什么必然联系嘛,就熟悉入门本身来说,多捣鼓还是好的
2017-12-15 10:19:04 +08:00
回复了 racecoder 创建的主题 C C++到底要怎么写
“ opencv ” “提取特征”

估计也是算法方面的,库和 api 是 c++接口。讲真这样的不要强求自己往学会写 c++代码上靠,就当做 c 来写反而不会出什么问题,对于算法类的程序来说,用 1k 行流水账 baby code 实现要比用一大堆 c++特性又是容器又是 trait 又各种 move 智能指针写完不过瘾再 future 并发一轮好得多,写出来又没人看得懂,看得懂的人说不准当魔法越玩越黑最后只剩 magic code 虽然不知道怎么回事但好像就是能对最后谁都不敢动。

对于从其它语言,特别是 C 转过来的人,我一般只劝他们把函数写进类里然后 static 掉,全局变量你给我放类里 static 掉,其它正常的 oo 语言转过来的( java )什么,c with class 模式能写熟练已经谢天谢地了,你实在对性能没什么概念就尽量多传指针,对,多传指针,跟你熟知引用是差不多的,释放的问题裸 delete 就裸吧裸能解决问题总比多线程智能指针+容器莫名其妙的多次析构好得多,大不了多几把锁,反正线程运行的时候又不干预,释放的时候保护冗余一点没什么大不了的

RAII 我都不指望你知道字面意思了,别忘记把基类析构 virtual 就行

在 c++里线程其实还是相当原始,异步和多线程下并发要格外小心
个人觉得初学 linux 有几点最重要(按顺序
1. 包管理 在安装绝大多数软件时不要考虑什么 sourceforge 下个 tarball 源码 make install 又是依赖又是系统版本的,最好是一行命令就能用,在这一点上 debian 系可以说领先其它发行版十条街
2. 桌面环境 初学一定要有 DE,而且最好是实体机上捣鼓,先把桌面搞漂亮,unity *dm xfce awsome 感受适应一下各种主流 DE/DM 的风格,切记一定选最大众最主流的,然后捣鼓一下终端,zsh 先装起来,美化先捣鼓起来,初学的时候什么服务器啊开发环境啊不都扯淡呢嘛,先捣鼓个第一眼能看到的效果满足一下成就渴望,哪怕 vim 还不会退出,先搞它几十个插件逼格装起来先,慢慢来不急
3. 社区 千万不要选小众版,不然出现问题都没处找 askubuntu 和 archwiki 独领天下,有时搜着搜着发现有比自己还小白的人居然已经问过更蠢的问题了瞬间会心安很多哦这早就有人问过了所以大概不是个大问题

然后可以开始着手入门了

deepin 目标是给朝鲜人用的
mint 给小清新
ubuntu 给异类桌面依赖的年轻人
debian 是中规中矩的学术型选手
centos 是学究老教授
arch=geeks
fedora=过时
kali=hacked debian

鉴于推荐 debian 系的原则,最好的路线大概是
deepin(3 天)-> ubuntu(几周) -> debian/mint(熟练) -> arch(有兴趣)/rasbian(有兴趣) -> centos(生产环境) -> 异类邪教

deepin 当做玩具玩玩,ubuntu 下被驱动折磨几轮,debian 返璞归真摸索自己口味,arch 开始 DE 已经不重要,滚动更新不挂最重要,这个时候基本已经跨过入门阶段了

然后是捣鼓各种东西的顺序
装,分区 /修复 linux 没了导致的 windows 无法引导 -> 美化桌面,美化终端,装显卡驱动崩成傻逼,换 de 崩成傻逼 -> 用 vim 和 awsome 装逼 -> 同步学习 lnmp/python -> 发现 apt 能装上一大堆东西 -> 熟悉各种配置文件和 shell script,产生重度 grep sed | 依赖 -> 折腾开源项目


最后提一句 虽说绝大多数人都推荐先用虚拟机尝试,但个人认为 uefi/grub/驱动 这种坑还是要踩的,而且本机直接装还能让你发现 linux 的某些潜力,在 linux 里玩 dota 和最小化掉虚拟机再点开 steam 感受是十分不同的
2017-12-08 11:37:24 +08:00
回复了 baskice 创建的主题 有人梦见过自己在开车吗?
我还记得很清楚由次梦到开车,不知道为什么紧急情况我的反应是拼命把档杆往 1 档推而不是踩刹车
@jakeyfly
你摆出来的这个例子并没有很好提现 iterable 和对应 iterator 的关系所以你没啥感觉
一个类确实可以同时实现 next 和 iter 两个内置方法,典型的你看 generator 对象就能被获取 iterator,也能调用 next,但对它自己调用 next 还是获取迭代器去访问它内部的元素,意义是完全不一样的

但从逻辑和结构上来说,iterable 是容器,iterator 是访问器,它们的功能就是不一样的。比如现在迭代器已经指向了容器中的某个位置,然后你需要把这个位置信息传递给其它方法去处理,那你肯定希望函数参数传的是一个迭代器,而不需要把原来的整个容器一并传进来;如果还不是很理解,下面这个不很好的例子起码能体现出区别

instance = MyIterable([1,2,3,4,5,6,7,8,9,10])#MyIterable 是随便什么 iterable 类
it = iter(instance)

print( *zip( it,it ) )
print( *zip( instance,instance ) )
print( *zip( *[iter(instance)]*2 ) )
Python 里的可迭代对象 iterable 和迭代器 iterator 令人迷惑得厉害
总的来说
迭代器 iterator 是可迭代对象 iterable 的 访问器
迭代器 iterator 原本应该是一个指针,也就说应该具有 iterator->obj::*这种语义,同时迭代器迭代位置还能移动,调用 iterator.__next__()能获取被迭代对象的下一个元素
iterable 保证能返回一个用于访问其内容的迭代器(或者随机访问器__getitem__),一般 iterable 是某种容器,容器中内容具体如何组织我们不关心,我们只关心怎么取出来然后怎么用,而组织“怎么取”,就是迭代器要做的工作

iterable 不仅包括迭代器关心的那些元素,还包括很多很多其它的东西,比如你可以把整个 v 站视为可迭代的,给它定义一个专门的迭代器对象用来浏览每一个帖子,当你 for 帖子 in v 站的时候这个迭代器帮你遍历所有帖子,但你还可以 v 站.refresh(),v 站.down(),v 站.block(uid)什么的,当你不需要遍历 iterable 的时候,iterable 本身还有很多其它的属性和方法
2017-12-01 14:13:31 +08:00
回复了 singvee 创建的主题 程序员 开源代码,编译不过,哪位大神知道怎么回事~~~
别管怎么编过,永远不要给 format 传可变参数,根本不该有这种需求,会造成严重的安全隐患
2017-11-16 10:29:39 +08:00
回复了 scarqin 创建的主题 程序员 浅谈 Sdk 与 Api,你是喜欢 SDK 还是 API?
恕我直言 mdzz
不要立个假靶子,是 concurrency 并发不是并行。
1 ... 137  138  139  140  141  142  143  144  145  146 ... 148  
关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2474 人在线   最高记录 6679   ·     Select Language
创意工作者们的社区
World is powered by solitude
VERSION: 3.9.8.5 · 49ms · UTC 15:50 · PVG 23:50 · LAX 07:50 · JFK 10:50
Developed with CodeLauncher
♥ Do have faith in what you're doing.