Golang 中国

在amazon的js脚本中,发现javascript的Math.sin(1e300)结果是-0.8178819121159085, python的math.sin(1e300)结果是0.9804836454796092。 看了一下sin的参数,都是用弧度表示,但计算结果不同。 所以想用golang来计算。fmt.Println(math.Sin(1e300))结果是”+Inf”.
不管结果是对是错,怎么才能用golang得到sin(1e300)呢?

24 回复
jimmykuu
#1 jimmykuu • 2017-09-12 16:39

pyhton 的 math.sin(1e300) 你怎么算出 0.9804836454796092 来的?

>>> import math
>>> math.sin(1e300)
-0.8178819121159087
gosenvei
#2 gosenvei • 2017-09-12 16:48

Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] on win32
Type “copyright”, “credits” or “license()” for more information.

import math
math.sin(1e300)
0.9804836454796092

我的python结果就是这样的。

tt_0411
#3 tt_0411 • 2017-09-12 18:16

go 计算的话, 运用三角函数公式啊

sin(a + 2*pi) = sin(a)
wpf000
#4 wpf000 • 2017-09-21 01:40

回2楼

看来是python的bug。32位的python解释器算出的结果不对,64位的python解释器算的是正确的:

Python 3.6.2 (v3.6.2:5fd33b5, Jul 8 2017, 04:57:36) [MSC v.1900 64 bit (AMD64)]
on win32
Type “help”, “copyright”, “credits” or “license” for more information.

import math
math.sin(1e300)
-0.8178819121159085

wpf000
#5 wpf000 • 2017-09-21 01:43

Lua计算结果也是对的

[root@ln0 ~]# lua
Lua 5.1.4  Copyright (C) 1994-2008 Lua.org, PUC-Rio
> print(math.sin(1e300))
-0.81788191211591
> 
snake117
#6 snake117 • 2017-09-21 02:33

@gosenvei @jimmykuu @wpf000

用golang计算,用如下算式:
fmt.Println(math.Sin(math.Mod(1e300, math.Pi*2))) fmt.Println(math.Sin(math.Remainder(1e300, math.Pi*2)))
结果基本一致:
-0.6619570086831917
-0.6619570086831915

反正不是-0.81788191211591,不知道哪个更准确

snake117
#7 snake117 • 2017-09-21 03:07

好吧,貌似都不够准确,big版本如下:

package main

import (
    "fmt"
    "math"
    "math/big"
)

func main() {
    F, _, _ := big.ParseFloat("1e300", 10, 5000, big.ToNearestEven)
    P, _, _ := big.ParseFloat(pi, 10, 5000, big.ToNearestEven)
    P.Mul(P, big.NewFloat(2))
    F.Quo(F, P)
    M, _ := F.Int(nil)
    N := big.NewFloat(0).SetPrec(5000).SetInt(M)
    F.Sub(F, N)
    F.Mul(F, P)
    f, _ := F.Float64()
    fmt.Println(math.Sin(f))
    /*fmt.Println(N.Add(N.Mul(N, P), F))*/
}

const pi = "3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912983367336244065664308602139494639522473719070217986094370277053921717629317675238467481846766940513200056812714526356082778577134275778960917363717872146844090122495343014654958537105079227968925892354201995611212902196086403441815981362977477130996051870721134999999837297804995105973173281609631859502445945534690830264252230825334468503526193118817101000313783875288658753320838142061717766914730359825349042875546873115956286388235378759375195778185778053217122680661300192787661119590921642019893809525720106548586327886593615338182796823030195203530185296899577362259941389124972177528347913151557485724245415069595082953311686172785588907509838175463746493931925506040092770167113900984882401285836160356370766010471018194295559619894676783744944825537977472684710404753464620804668425906949129331367702898915210475216205696602405803815019351125338243003558764024749647326391419927260426992279678235478163600934172164121992458631503028618297455570674983850549458858692699569092721079750930295532116534498720275596023648066549911988183479775356636980742654252786255181841757467289097777279380008164706001614524919217321721477235014144197356854816136115735255213347574184946843852332390739414333454776241686251898356948556209921922218427255025425688767179049460165346680498862723279178608578438382796797668145410095388378636095068006422512520511739298489608412848862694560424196528502221066118630674427862203919494504712371378696095636437191728746776465757396241389086583264599581339047802759009946576407895126946839835259570982582262052248940772671947826848260147699090264013639443745530506820349625245174939965143142980919065925093722169646151570985838741059788595977297549893016175392846813826868386894277415599185592524<BR>59539594310499725246808459872736446958486538367362226260991246080512438843904512441365497627807977156914359977001296160894416948685558484063534220722258284886481584560285060168427394522674676788952521385225499546667278239864565961163548862305774564980355936345681743241125"

结果输出是-0.985750425160377

snake117
#8 snake117 • 2017-09-21 03:14

1,5000位的pi值,计算结果也是-0.985750425160377

wpf000
#9 wpf000 • 2017-09-21 22:55

@snake117

[root@ln0 ~]# python


Python 2.7.13 |Anaconda 4.3.0 (64-bit)| (default, Dec 20 2016, 23:09:15) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-1)] on linux2
Type "help", "copyright", "credits" or "license" for more information.
Anaconda is brought to you by Continuum Analytics.
Please check out: http://continuum.io/thanks and https://anaconda.org
>>> 
>>> 
>>> import math
>>> math.sin(10**300)
-0.8178819121159085
>>> 
[1]+  Stopped                 python
[root@ln0 ~]# python3
Python 3.5.2 (default, Jul 23 2016, 13:21:49) 
[GCC 4.4.7 20120313 (Red Hat 4.4.7-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import math
>>> math.sin(10**300)
-0.8178819121159085
>>> 
wpf000
#10 wpf000 • 2017-09-22 15:06

7楼厉害

Python 3.5.2 (default, Sep 18 2017, 15:49:27) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> 
>>> from decimal import Decimal as D
>>> from decimal import getcontext  
>>> getcontext()
Context(prec=28, rounding=ROUND_HALF_EVEN, Emin=-999999, Emax=999999, capitals=1, clamp=0, flags=[], traps=[InvalidOperation, DivisionByZero, Overflow])
>>> getcontext().prec=350
>>> high_prec_pi=D('3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196442881097566593344612847564823378678316527120190914564856692346034861045432664821339360726024914127372458700660631558817488152092096282925409171536436789259036001133053054882046652138414695194151160943305727036575959195309218611738193261179310511854807446237996274956735188575272489122793818301194912')
>>> n=D(5)/high_prec_pi*10**299
>>> n
Decimal('159154943091895335768883763372514362034459645740456448747667344058896797634226535090113802766253085956072842726757958036892911846114578652877967410731699839229239966937409077573077746396925307688717392896217397661693362390241723629011832380114222699755715940461890086902673956120489410936937844085528.72309994644340024867234773945961089832309678307491')
>>> 
>>> import math
>>> result=math.sin(0.72309994644340024867234773945961089832309678307491*2*math.pi)
>>> result
-0.9857504251603769
>>> 
jinheking
#11 jinheking • 2017-09-27 09:48

这个问题很有趣

jimmykuu
#12 jimmykuu • 2017-09-27 18:08

这个问题似乎是 Go 的一个 Bug,还没解决,可以看这两个 Issue:

math.Cos(1.23e300) != 0.251533

math: trigonometric argument reduction fails for huge arguments

snake117
#13 snake117 • 2017-09-28 14:50

@jimmykuu

我觉得这算不上bug吧,数值太大了,精度问题肯定会体现出来的。

很可能这就是编译型语言的固有特性。

谁有C、C++的计算结果吗?

还有C#、java的?

jimmykuu
#14 jimmykuu • 2017-09-28 16:08

nim:

import math

echo math.sin(1e300)

result:

-0.8178819121159087
jimmykuu
#15 jimmykuu • 2017-09-28 16:18

java:

import java.lang.Math;

public class Sin {
    public static void main(String[] args) {
        System.out.println(Math.sin(1e300));
    }
}

result:

-0.8178819121159085
snake117
#16 snake117 • 2017-09-29 17:06

@jimmkuu 我测试了C和C++,确实都是-0.8178819121159085,看来go确实是有问题了。

496543679
#17 496543679 • 2017-10-05 20:36

vs2013下测试结果为0.980484

496543679
#18 496543679 • 2017-10-05 20:43

VC++ 6.00结果为0.980484

496543679
#19 496543679 • 2017-10-05 20:46

dev c++ 5.11 32位 结果为-0.817882

496543679
#20 496543679 • 2017-10-05 20:47

dev c++ 5.11 64位 结果为-0.817882

496543679
#21 496543679 • 2017-10-05 21:53

Windows 计算器

496543679
#22 496543679 • 2017-10-06 09:15

Matlab计算结果是多少?

496543679
#23 496543679 • 2017-10-06 09:30

matlab在线计算结果为-0.81788
https://is.golangtc.com/upload/image/b3fe9ab8aa3511e7b95b00163e0090de.jpg

到底哪个正确?

wingkeewei
#24 wingkeewei • 2017-10-17 11:34

用octvate在线计算:

方法一,结果:
octave:242> sin( 1e300 )
ans = -0.817881912115909

方法二,结果:
octave:243> sin( vpa(1e300, 600) )
ans = (sym)

-0.817881912115908597045885282755426212011428303890384046463739586101665985875…

方法三,结果:
octave:244> sin( vpa(‘1e300’, 600) )
ans = (sym)

-0.985750425160376996609047531429895469077715312561026993159237184495777977005…


也是出现两个争议中的答案!再尝试比较一下两个输入参数vpa(1e300, 600) 和 vpa(‘1e300’, 600)有什么不同:

octave:268> vpa(1e300,600)
ans = (sym)
100000000000000005250476025520442024870446858110815915491585411551180245798890
819578637137508044786404370444383288387817694252323536043057564479218478670698
284838720092657580373783023379478809005936895323497079994508111903896764088007
4652742780142494579258788820056842838115669472196386865459400540160.0000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000


octave:267> vpa(‘1e300’,600)
ans = (sym)
100000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000000000000000.0000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000000000000000000000000000000000000000000000
0000000000000000000000000000000000000000000000000000000


这个可能不是最后的答案,不过应该还是精度问题

需要 登录 后方可回复, 如果你还没有账号你可以 注册 一个帐号。