Qalculate / libqalculate

Qalculate! library and CLI
https://qalculate.github.io/
GNU General Public License v2.0
1.88k stars 151 forks source link

isInteger(…) false negatives #663

Closed xBZZZZ closed 5 months ago

xBZZZZ commented 5 months ago

version: 92faec94811d5b2b1617bbbdac1ac6051fb6bfd8

> exact
> 0.1^log10(0.01)

  0.1^log10(0.01) = 100^(ln(10) / ln(10))

> 0.1^log10(0.01) = 100

  ((0.1^log10(0.01)) = 100) = true

> isInteger(100)

  isInteger(100) = 1

> isInteger(0.1^log10(0.01))

  isInteger(0.1^log10(0.01)) = 0

> x+1

  x + 1 = x + 1

> isInteger(x)

  isInteger(x) = 0
hanna-kn commented 5 months ago

isInteger() is an utility function primarily for use in other functions (e.g. in Fibonacci function: if(isInteger(\1),(golden^\1−(1−golden)^\1)/sqrt(5),(golden^\x-cos(\x*pi*rad)*golden^(-\x))/sqrt(5))) and tests if the argument is explicitly an integer (is of integer type). 0.1^log10(0.01) is approximated as an floating point interval and therefor returns false. isRational(), isReal(), and isNumber() exhibits the same behaviour.

This behaviour should either be properly documented or changed.

xBZZZZ commented 5 months ago

What is representsInteger (seems like isInteger with less false negatives)?

isInteger(100) = 1
representsInteger(100) = 1

isInteger(0.1^log10(0.01)) = 0
representsInteger(0.1^log10(0.01)) = 0

isInteger(x) = 0
representsInteger(x) = 0

isInteger(trunc(x)) = 0
representsInteger(trunc(x)) = 1

isInteger(floor(x)) = 0
representsInteger(floor(x)) = 1

isInteger(ceil(x)) = 0
representsInteger(ceil(x)) = 1

isInteger(round(x)) = 0
representsInteger(round(x)) = 0
hanna-kn commented 5 months ago

The behaviour can be summarized as: false negatives are allowed, false positives are not.

I've now added descriptions and examples to the functions, fixed some false negatives (representsInteger(round(x)), and implemented exact calculation of log10() for negative integer return values.