aymano.osman
2020-6-16 16:33:11

Is there an alternative to the log function that returns the correct result (3.0) for (log 1000 10), currently it returns 2.9999999999999996?


sorawee
2020-6-16 18:11:39

You can use fllogb from math/flonum library. Note that the arguments are in the different order.


soegaard2
2020-6-16 18:13:43

@aymano.osman That’s just the nature of floating points. Do you need an exact result?

If you need an exact result you can use a cas instead. It computes symbolical so it will give an exact result, but will be slower.

#lang racket (require racket-cas) (normalize '(log 10 1000)) This will return 3.


aymano.osman
2020-6-16 18:13:57

Thank you so much @sorawee!


aymano.osman
2020-6-16 18:22:28

Why does fllogb get it right, out of interest?


aymano.osman
2020-6-16 18:22:51

@soegaard2 Thanks, I’ll take a look at that.


soegaard2
2020-6-16 18:25:58

Good question! Looking at the code: it first uses fllog to compute the standard floating point logarithm. It then does a one Newton iteration. https://github.com/racket/math/blob/58f5d6205abeec854b47a6c70d613089f108bceb/math-lib/math/private/flonum/flonum-log.rkt#L138


aymano.osman
2020-6-16 18:30:19

Wow, that is interesting.

Just noticed that python behaves the same way, it just has a specific function for log base 10

>>> math.log10(1000) 3.0 >>> math.log(1000, 10) 2.9999999999999996


soegaard2
2020-6-16 18:31:23

Do you need an exact result? - if not, I recommend using the standard log . If the result is printed, you normally round it first and it will print as 3.0 anyway. If you need to compare it to something else - then use (<= (- a b) a-small-number-close-to-zero).


aymano.osman
2020-6-16 18:32:00

kotlin produces the same results println(log10(1000.0)) println(log(1000.0, 10.0)) So my understanding was wrong.


aymano.osman
2020-6-16 18:33:19

I was using the maths trick that log base 10 counts the number of digits (minus 1) in a number. (I was doing a silly code challenge online)


soegaard2
2020-6-16 18:33:53

Floating points in various languages are usually represented as in the IEEE standard.


soegaard2
2020-6-16 18:35:45

Back in the day you could buy a “math coprocessor” that could compute with these floating point numbers - and take logarithms etc. I think most cpus these days has floating point support.


soegaard2
2020-6-16 18:36:44

Programming languages normally implement log simply by letting the cpu compute the result. This explains why you get the same result in multiple languages.


soegaard2
2020-6-16 18:37:58

However there is a tension between speed and accuracy. Sometimes the floating point operations won’t return the most precise result.


aymano.osman
2020-6-16 18:39:36

I wonder if it would be appropriate for racket to also provide a specialised log10 like these other languages do?


soegaard2
2020-6-16 18:40:00

(log 1000 10) computes log10.


soegaard2
2020-6-16 18:41:39

Ah - now I get what you mean.


aymano.osman
2020-6-16 18:41:47

Say you want to use log to “count number of digits” in a number.


soegaard2
2020-6-16 18:42:47

Then you would use: (inexact->exact (floor (log x)))


aymano.osman
2020-6-16 18:42:51

You want numbers between 1000 and 9999 (inclusive) to all compute 3 – 3.99999999999


aymano.osman
2020-6-16 18:43:37

If you floor (log 1000 10) you get 2, which is the problem :slightly_smiling_face:


soegaard2
2020-6-16 18:44:17

Hmm.


aymano.osman
2020-6-16 18:44:27

(floor (log &lt;1000-9999&gt; 10)) == 3 <- this needs to hold


aymano.osman
2020-6-16 18:45:03

It’s a silly use-case, so no need to worry about it.


sorawee
2020-6-16 18:45:20

If you want the number of digits, (compose1 string-length number-&gt;string) also works


soegaard2
2020-6-16 18:45:29

I suppose that’s why fllogb says:


soegaard2
2020-6-16 18:46:04

It’s not silly at all.


aymano.osman
2020-6-16 18:46:05

@sorawee remember I’m doing a silly code-challenge where speed and memory usage is an issue :slightly_smiling_face:


soegaard2
2020-6-16 18:47:40

Euler Project?


sorawee
2020-6-16 18:47:48

unless you do get a timeout/memory error from the contest, I’d say this is a premature optimization.


aymano.osman
2020-6-16 18:47:56

@soegaard2 leetcode


soegaard2
2020-6-16 18:48:31

Looks like fllogb is what you need for this problem.


aymano.osman
2020-6-16 18:48:53

@sorawee well I improved my rank a lot with this little trick, so I’m quite satisfied :slightly_smiling_face:


sorawee
2020-6-16 18:49:31

wait, so the rank depends on the running time too?


aymano.osman
2020-6-16 18:49:40

Why let a neat maths trick go to waste?


aymano.osman
2020-6-16 18:49:52

Yes, everything counts. Memory usage too.


sorawee
2020-6-16 18:50:05

Then why don’t you use C lol


soegaard2
2020-6-16 18:50:44

The official Python docs says:


sorawee
2020-6-16 18:50:52

If you are serious about getting good ranking that is


soegaard2
2020-6-16 18:50:59

Do you happen to know where one can find the implementation?


sorawee
2020-6-16 18:51:39

Racket is not known for speed. The program is reasonably efficient, but not super efficient


aymano.osman
2020-6-16 18:51:43

I have been implementing each challenge in multiple languages at the same time for fun. Each language is ranked separately.


aymano.osman
2020-6-16 18:52:44

It is mainly as prep for coding interviews too.


aymano.osman
2020-6-16 18:53:26

thank you both for your help


soegaard2
2020-6-16 19:24:23

@aymano.osman Since log10(10^n–1)<log10(10^n) we can add a number smaller than the difference between them before flooring:

(define (len x) (inexact-&gt;exact (floor (+ (log x 10) 0.0000000000001))))


soegaard2
2020-6-16 19:25:17

Should work even for very large numbers.


badkins
2020-6-16 20:30:21

@aymano.osman I just took a look at leetcode, and the list of default languages is rather small - what was necessary to use Racket on that site?


badkins
2020-6-16 20:31:18

FWIW in Julia log10(1000)=> 3.0


aymano.osman
2020-6-16 20:42:23

I was using kotlin on the website and repeating the implementations in Haskell and Racket outside.


okcohen
2020-6-17 01:05:53

@okcohen has joined the channel