Pathological floating point problems: Difference between revisions
Content added Content deleted
(Add Swift) |
|||
Line 3,686: | Line 3,686: | ||
+1.b7e151628aed3X+000 |
+1.b7e151628aed3X+000 |
||
</pre> |
</pre> |
||
=={{header|Swift}}== |
|||
Using mkrd's Swift-BigInt library. |
|||
<lang swift>extension Numeric where Self: Strideable { |
|||
@inlinable |
|||
public func power(_ n: Self) -> Self { |
|||
return stride(from: 0, to: n, by: 1).lazy.map({_ in self }).reduce(1, *) |
|||
} |
|||
} |
|||
protocol PathologicalFloat: SignedNumeric, Strideable, ExpressibleByFloatLiteral { |
|||
static var e: Self { get } |
|||
static func /(_ lhs: Self, _ rhs: Self) -> Self |
|||
} |
|||
extension Double: PathologicalFloat { |
|||
static var e: Double { Double("2.71828182845904523536028747135266249")! } |
|||
} |
|||
extension Float: PathologicalFloat { |
|||
static var e: Float { Float("2.7182818284590")! } |
|||
} |
|||
extension Decimal: PathologicalFloat { |
|||
static var e: Decimal { Decimal(string: "2.71828182845904523536028747135266249")! } |
|||
} |
|||
extension BDouble: PathologicalFloat { |
|||
static var e: BDouble { BDouble("2.71828182845904523536028747135266249")! } |
|||
public func advanced(by n: BDouble) -> BDouble { self + n } |
|||
public func distance(to other: BDouble) -> BDouble { abs(self - other) } |
|||
} |
|||
func badSequence<T: PathologicalFloat>(n: Int) -> T { |
|||
guard n != 1 else { return 2 } |
|||
guard n != 2 else { return -4 } |
|||
var a: T = 2, b: T = -4 |
|||
for _ in stride(from: 2, to: n, by: 1) { |
|||
(a, b) = (b, 111 - 1130 / b + 3000 / (a * b)) |
|||
} |
|||
return b |
|||
} |
|||
func chaoticBank<T: PathologicalFloat>(years: T) -> T { |
|||
var balance = T.e - 1 |
|||
for year: T in stride(from: 1, through: 25, by: 1) { |
|||
balance = (balance * year) - 1 |
|||
} |
|||
return balance |
|||
} |
|||
func rumpFunction<T: PathologicalFloat>(_ a: T, _ b: T) -> T { |
|||
let aSquared = a.power(2) |
|||
let bSix = b.power(6) |
|||
let f1 = 333.75 * bSix |
|||
let f2 = aSquared * (11 * aSquared * b.power(2) - bSix - 121 * b.power(4) - 2) |
|||
let f3 = 5.5 * b.power(8) + a / (2 * b) |
|||
return f1 + f2 + f3 |
|||
} |
|||
func fmt<T: CVarArg>(_ n: T) -> String { String(format: "%16.16f", n) } |
|||
print("Bad sequence") |
|||
for i in [3, 4, 5, 6, 7, 8, 20, 30, 50, 100] { |
|||
let vFloat: Float = badSequence(n: i) |
|||
let vDouble: Double = badSequence(n: i) |
|||
let vDecimal: Decimal = badSequence(n: i) |
|||
let vBigDouble: BDouble = badSequence(n: i) |
|||
print("v(\(i)) as Float \(fmt(vFloat)); as Double = \(fmt(vDouble)); as Decimal = \(vDecimal); as BDouble = \(vBigDouble.decimalExpansion(precisionAfterDecimalPoint: 16, rounded: false))") |
|||
} |
|||
let bankFloat: Float = chaoticBank(years: 25) |
|||
let bankDouble: Double = chaoticBank(years: 25) |
|||
let bankDecimal: Decimal = chaoticBank(years: 25) |
|||
let bankBigDouble: BDouble = chaoticBank(years: 25) |
|||
print("\nChaotic bank") |
|||
print("After 25 years your bank will be \(bankFloat) if stored as a Float") |
|||
print("After 25 years your bank will be \(bankDouble) if stored as a Double") |
|||
print("After 25 years your bank will be \(bankDecimal) if stored as a Decimal") |
|||
print("After 25 years your bank will be \(bankBigDouble.decimalExpansion(precisionAfterDecimalPoint: 16, rounded: false)) if stored as a BigDouble") |
|||
let rumpFloat: Float = rumpFunction(77617.0, 33096.0) |
|||
let rumpDouble: Double = rumpFunction(77617.0, 33096.0) |
|||
let rumpDecimal: Decimal = rumpFunction(77617.0, 33096.0) |
|||
let rumpBigDouble: BDouble = rumpFunction(77617.0, 33096.0) |
|||
print("\nRump's function") |
|||
print("rump(77617.0, 33096.0) as Float \(rumpFloat); as Double = \(rumpDouble); as Decimal = \(rumpDecimal); as BDouble = \(rumpBigDouble.decimalExpansion(precisionAfterDecimalPoint: 16, rounded: false))")</lang> |
|||
{{out}} |
|||
<pre>Bad sequence |
|||
v(3) as Float 18.5000000000000000; as Double = 18.5000000000000000; as Decimal = 18.5; as BDouble = 18.5000000000000000 |
|||
v(4) as Float 9.3783798217773438; as Double = 9.3783783783783790; as Decimal = 9.378378378378378378378378378378378379; as BDouble = 9.3783783783783783 |
|||
v(5) as Float 7.8011646270751953; as Double = 7.8011527377521688; as Decimal = 7.8011527377521613832853025936598347208; as BDouble = 7.8011527377521613 |
|||
v(6) as Float 7.1545600891113281; as Double = 7.1544144809753334; as Decimal = 7.154414480975249353527890653858927037; as BDouble = 7.1544144809752493 |
|||
v(7) as Float 6.8088302612304688; as Double = 6.8067847369248113; as Decimal = 6.806784736923632983941756596252083488; as BDouble = 6.8067847369236329 |
|||
v(8) as Float 6.6227531433105469; as Double = 6.5926327687217920; as Decimal = 6.592632768704438392742002776072632593; as BDouble = 6.5926327687044383 |
|||
v(20) as Float 100.0000000000000000; as Double = 98.3495031221653591; as Decimal = 6.043552110189180069946503928146085357; as BDouble = 6.0435521101892688 |
|||
v(30) as Float 100.0000000000000000; as Double = 99.9999999999989342; as Decimal = 5.864835170633765923137784097537303066; as BDouble = 6.0067860930312057 |
|||
v(50) as Float 100.0000000000000000; as Double = 100.0000000000000000; as Decimal = 100.00000000000000000002294175104747792; as BDouble = 6.0001758466271871 |
|||
v(100) as Float 100.0000000000000000; as Double = 100.0000000000000000; as Decimal = 100; as BDouble = 6.0000000193194779 |
|||
Chaotic bank |
|||
After 25 years your bank will be -1.2804254e+18 if stored as a Float |
|||
After 25 years your bank will be -2242373258.570158 if stored as a Double |
|||
After 25 years your bank will be 0.03993872955290591987527254016 if stored as a Decimal |
|||
After 25 years your bank will be 0.0399387295529059 if stored as a BigDouble |
|||
Rump's function |
|||
rump(77617.0, 33096.0) as Float -6.338253e+29; as Double = -1.1805916207174113e+21; as Decimal = -1; as BDouble = -0.8273960599468213</pre> |
|||
=={{header|TI-83 BASIC}}== |
=={{header|TI-83 BASIC}}== |