You aren't doing you computations on Long
, you use Int
everywhere and only widen the result to Long
once it's done. If you actually use Long
, like this:
def fib(n:Long):Long={
@tailrec def fibTail( n: Long, a:Long, b:Long): Long = n match {
case 0 => a
case _ => fibTail( n-1, b, a+b )
}
return fibTail( n, 0, 1)
}
then integer overflow seems to happens a bit later
@ for (tryit<-1 to 10) println(tryit + ": " + fib(tryit))
1: 1
2: 1
3: 2
4: 3
5: 5
6: 8
7: 13
8: 21
9: 34
10: 55
@ for (breakit<-10 to 100 by 10) println(breakit + ": " + fib(breakit))
10: 55
20: 6765
30: 832040
40: 102334155
50: 12586269025
60: 1548008755920
70: 190392490709135
80: 23416728348467685
90: 2880067194370816120
100: 3736710778780434371
@ for (overflow<-1 to 8) println("10^" + overflow + ": " + fib(math.pow(10,overflow).toLong))
10^1: 55
10^2: 3736710778780434371
10^3: 817770325994397771
10^4: -2872092127636481573
10^5: 2754320626097736315
10^6: -4249520595888827205
10^7: -8398834052292539589
10^8: -4307732722963583941
But even with Long
fib
overflows between 10^1 and 10^2 as we can see if we use BigInt
implementation:
@ def fib(n: BigInt): BigInt = {
@scala.annotation.tailrec def fibTail( n: BigInt, a:BigInt, b:BigInt): BigInt =
if (n == BigInt(0)) a
else fibTail( n-1, b, a+b )
fibTail( n, BigInt(0), BigInt(1))
}
@ for (overflow<-1 to 8) println("10^" + overflow + ": " + fib(BigInt(math.pow(10,overflow).toLong)))
10^1: 55
10^2: 354224848179261915075
10^3: 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
10^4: 33644764876431783266621612005107543310302148460680063906564769974680081442166662368155595513633734025582065332680836159373734790483865268263040892463056431887354544369559827491606602099884183933864652731300088830269235673613135117579297437854413752130520504347701602264758318906527890855154366159582987279682987510631200575428783453215515103870818298969791613127856265033195487140214287532698187962046936097879900350962302291026368131493195275630227837628441540360584402572114334961180023091208287046088923962328835461505776583271252546093591128203925285393434620904245248929403901706233888991085841065183173360437470737908552631764325733993712871937587746897479926305837065742830161637408969178426378624212835258112820516370298089332099905707920064367426202389783111470054074998459250360633560933883831923386783056136435351892133279732908133732642652633989763922723407882928177953580570993691049175470808931841056146322338217465637321248226383092103297701648054726243842374862411453093812206564914032751086643394517512161526545361333111314042436854805106765843493523836959653428071768775328348234345557366719731392746273629108210679280784718035329131176778924659089938635459327894523777674406192240337638674004021330343297496902028328145933418826817683893072003634795623117103101291953169794607632737589253530772552375943788434504067715555779056450443016640119462580972216729758615026968443146952034614932291105970676243268515992834709891284706740862008587135016260312071903172086094081298321581077282076353186624611278245537208532365305775956430072517744315051539600905168603220349163222640885248852433158051534849622434848299380905070483482449327453732624567755879089187190803662058009594743150052402532709746995318770724376825907419939632265984147498193609285223945039707165443156421328157688908058783183404917434556270520223564846495196112460268313970975069382648706613264507665074611512677522748621598642530711298441182622661057163515069260029861704945425047491378115154139941550671256271197133252763631939606902895650288268608362241082050562430701794976171121233066073310059947366875
10^5: 259740693472217241661550340212759154148804853865176965847247707039525345435112736862655567728367167447546375872230744321116383994738750910309656973821883044930522876385313349213530267927895670105127657827163560807305053220024323311438398651613782723812477745377833729991621463405005466986039086275099663936640921189012527196017210506030035058689402855810367511765825136837743868493641345733883436515877542537191241050033219599133006220436303521375652542182399869084855637408017925176162939175496345855861630076281991608110983652635299544069428420657104604490380564713634603300052085227770755444679472370903097901901486043284681985796101595100185060826491923458731339915013391993236310230186417253647713626647508013398243123170343145296418179005118795731676683497990168201184990775668645684506628739248560391404760519955006628882634587718941068037009187936500173301171002831047394745625609144493282137485557386408057981302826664027035429441210491999580313187680589918651342517595991152056315533770399694103551827527491995980225750790203779810308992298499630449625581404551700025029976432219346216536621084187674542829826139823447836658158804081900330738293950008213200937471548513102722081730543226486694963098791471436292555425262404399961532697987680751064681906879211829916796440917827186856170291810221267926740136265049978496884368097525470013100457418640644829948587255174474669565187912691699324456481767332225714931496776334584662383033382023970243...
which is expected because while argument of fib(100)
is well within the range of Int
and Long
, the value returned is way outside of it.
@ Long.MaxValue
res14: Long = 9223372036854775807L
@ 354224848179261915075L // fib(10^2)
(console):1: integer number too large
354224848179261915075L