|
有一类英文名为idle的数值膨胀游戏,名叫“懒人游戏”/“放置游戏”
那里面爆double(大于等于1.7976931348623159e308)只是开始
在那里,数字会以另外的形式进行存储
比如一般情况下那里会直接存储lg 数字,而不是数字本身。
当你有两个小数字,比如13和5,你实际上只储存了lg(13)~1.1139433523068367204444939488894306123256683349609375
和
lg(5)~0.69897000433601885749368420874816365540027618408203125
当你试图计算它们的加减法时,你应当将它们恢复成普通数字,然后相加减
恢复时候,可以将两个数字分别减去它们的最大者的整数部分,比如这里可以使用
lg(13)-1~0.1139433523068367204444939488894306123256683349609375
和
lg(5)-1~-0.30102999566398114250631579125183634459972381591796875
进行恢复,恢复得到的两个数字大致为1.2999999999999998和0.5000000000000001,相加得
1.79999999999999982236431605997495353221893310546875
之后再将这个数字求lg,结果加上之前减掉的整数部分,就得到了最终结果,1.255272505103306013296560195158235728740692138671875
这个结果大概对应17.999999999999996
fn add(a:f64,b:f64)->f64{
let c=a.fract();
let d=b-a.trunc();
let e=10f64.powf(c)+10f64.powf(d);
let f=e.log10()+a.trunc();
println!("{:102.99}\n{:102.99}\n{:102.99}\n{:102.99}\n{:102.99}\n{:102.99}\n\nadd1={},add2={},ans={}",a,b,c,d,e,f,10f64.powf(a),10f64.powf(b),10f64.powf(f));
f // ans
}
fn main(){
add(13f64.log10(),5f64.log10());
}
使用这样的算法可以表示类似3.2e9999999这样的天文数字
类似的数字,真的是,显示问题比程序问题更离谱。
<hr/>当然,直接存储lg(x)并不能带来除了便于理解之外的其他好处
直接上ln,exp,expm1,log1p之类的神奇函数也是一个可行的选择。 |
|