objecthub / swift-numberkit

Advanced numeric data types for Swift 5, including BigInt, Rational, and Complex numbers.
Apache License 2.0
54 stars 15 forks source link

doubleValue returns incorrect infinities and NaNs and zeroes #17

Open detreville opened 1 year ago

detreville commented 1 year ago

With Rational<BigInt> values, incorrect infinities or NaNs or zeroes are returned for doubleValue when the numerators or denominator or both are too large themselves to fit inside a Double, even when the values themselves fit.

It would be great to document this behavior or even to correct for it.

Example test program:

import Foundation
import NumberKit

var x: Rational<BigInt> = 1

while true {
  print("\(x)")
  print("numerator.doubleValue = \(x.numerator.doubleValue)")
  print("denominator.doubleValue = \(x.denominator.doubleValue)")
  print("doubleValue = \(x.doubleValue)")
  if x.doubleValue.isNaN {
    break
  }
  x *= 101
  x /= 100
  print()
}

Example test output:

...

449290712499035178136313067576445965611259479254722670514813444007703755277757233626012171465497954998012097338429625913922663389615772353420792692877397988852736997750126238302536602889821678795213590136955628111947677132802585714228163560288611949064673775051015631052360866493066504213939770088265101/100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
numerator.doubleValue = 4.4929071249903515e+302
denominator.doubleValue = 1e+302
doubleValue = 4.492907124990351

45378361962402552991767619825221042526737207404726989721996157844778079283053480596227229318015293454799221831181392217306189002351193007695500061980617196874126436772762750068556196891871989558316572603832518439306715390413061157137044519589149806855532051280152578736288447515799716925607916778914775201/10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
numerator.doubleValue = 4.537836196240255e+304
denominator.doubleValue = 1e+304
doubleValue = 4.537836196240256

4583214558202657852168529602347325295200457947877425961921611942322586007588401540218950161119544638934721404949320613947925089237470493777245506260042336884286770114049037756924175886079070945389973832987084362369978254431719176870841496478504130492408737179295410452365133199095771409486399594670392295301/1000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
numerator.doubleValue = 4.583214558202658e+306
denominator.doubleValue = 1e+306
doubleValue = 4.583214558202658

462904670378468443069021489837079854815246252735620022154082806174581186766428555562113966273074008532406861899881382008740434012984519871501796132264276025312963781518952813449341764493986165484387357131695520599367803697603636863954991144328917179733282455108836455688878453108672912358126359061709621825401/100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
numerator.doubleValue = inf
denominator.doubleValue = 1e+308
doubleValue = inf

46753371708225312749971170473545065336339871526297622237562363423632699863409284111773510593580474861773093051888019582882783835311436507021681409358691878556609341933414234158383518213892602713923123070301247580536148173457967323259454105577220635153061527965992482024576723763975964148170762265232671804365501/10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
numerator.doubleValue =   inf
denominator.doubleValue = inf
doubleValue = nan