Hi,
how can I convert a float number to a integer number? Ok, there are floor, truncate, round, but the result have always a dot in it. I'd like to convert the number - it is (round (time->seconds (current-time))) - to a string without the dot.
Thanks for help!
Christoph Bauer
Afficher les réponses par date
Hallo,
Christoph Bauer wrote:
Hi,
how can I convert a float number to a integer number? Ok, there are floor, truncate, round, but the result have always a dot in it. I'd like to convert the number - it is (round (time->seconds (current-time)))
- to a string without the dot.
Thanks for help!
INEXACT->EXACT: http://www.schemers.org/Documents/Standards/R5RS/HTML/r5rs-Z-H-9.html#%_idx_...
Hi,
This is no doubt Very Bad Practice but it's useful :)
(define flonum->fixnum (c-lambda (double) int "___result = (int)___arg1;"))
Cheers, Darren
Christoph Bauer wrote:
Hi,
how can I convert a float number to a integer number? Ok, there are floor, truncate, round, but the result have always a dot in it. I'd like to convert the number - it is (round (time->seconds (current-time)))
- to a string without the dot.
Thanks for help!
Christoph Bauer _______________________________________________ Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
Date: Thu, 30 Oct 2008 08:37:32 +1000 From: Darren Baker darren@wildfire.com.au
This is no doubt Very Bad Practice but it's useful :)
(define flonum->fixnum (c-lambda (double) int "___result = (int)___arg1;"))
That's absurd! Aside from the obvious absurdity of calling out to C for this, it leads to nasal demons if the range of the argument's integral part exceeds the range of C ints or Gambit fixnums. There is a perfectly good standard procedure to obtain the nearest exact number to an inexact one, which one may have obtained by rounding another inexact number. This procedure is called INEXACT->EXACT.
Hi Taylor,
I do agree but it's only *mostly* absurd I would argue. :)
If I know I have a flonum within a known range, and I always want it as a fixnum, then this does the job, and I imagine skips a bunch of checks that would be irrelevant in this case (pls correct me if wrong though!)
If you use (##c-code ... ) inline then the C callout is gone... and on GCC / Intel the conversion will compile to a cvttsd2si instruction.
I am just putting a pragmatic / performance view here, it's definitely not elegant.
Obviously if inexact->exact has higher performance, eg because it's an optimizable intrinsic, then this method is categorically rubbish. :) I haven't checked yet though.
Cheers, Darren
Taylor R Campbell wrote:
Date: Thu, 30 Oct 2008 08:37:32 +1000 From: Darren Baker darren@wildfire.com.au
This is no doubt Very Bad Practice but it's useful :)
(define flonum->fixnum (c-lambda (double) int "___result = (int)___arg1;"))
That's absurd! Aside from the obvious absurdity of calling out to C for this, it leads to nasal demons if the range of the argument's integral part exceeds the range of C ints or Gambit fixnums. There is a perfectly good standard procedure to obtain the nearest exact number to an inexact one, which one may have obtained by rounding another inexact number. This procedure is called INEXACT->EXACT.
If you know your flonum is within the range of fixnums you can use the very efficient ##flonum->fixnum which will basically compile to a cast (correct me Marc if i'm wrong).
On Wed, Oct 29, 2008 at 8:20 PM, Darren Baker darren@wildfire.com.auwrote:
Hi Taylor,
I do agree but it's only *mostly* absurd I would argue. :)
If I know I have a flonum within a known range, and I always want it as a fixnum, then this does the job, and I imagine skips a bunch of checks that would be irrelevant in this case (pls correct me if wrong though!)
If you use (##c-code ... ) inline then the C callout is gone... and on GCC / Intel the conversion will compile to a cvttsd2si instruction.
I am just putting a pragmatic / performance view here, it's definitely not elegant.
Obviously if inexact->exact has higher performance, eg because it's an optimizable intrinsic, then this method is categorically rubbish. :) I haven't checked yet though.
Cheers, Darren
Taylor R Campbell wrote:
Date: Thu, 30 Oct 2008 08:37:32 +1000 From: Darren Baker darren@wildfire.com.au
This is no doubt Very Bad Practice but it's useful :)
(define flonum->fixnum (c-lambda (double) int "___result = (int)___arg1;"))
That's absurd! Aside from the obvious absurdity of calling out to C for this, it leads to nasal demons if the range of the argument's integral part exceeds the range of C ints or Gambit fixnums. There is a perfectly good standard procedure to obtain the nearest exact number to an inexact one, which one may have obtained by rounding another inexact number. This procedure is called INEXACT->EXACT.
-- Darren Baker CEO, CTO Wildfire Studios Pty. Ltd. Ph: +61 7 3844 1000 Fax: +61 7 3844 8970 www.wildfire.com.au
The information in this message is confidential and may be legally privileged. It is intended solely for the addressee. Access to this message by anyone else is unauthorised. If you are not the intended recipient, any disclosure, copying or distribution of the message, or any action taken by you in reliance on it, is prohibited and may be unlawful. If you have received this message in error, please delete it and contact the sender immediately. Thank you.
Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
On 29-Oct-08, at 8:49 PM, Guillaume Cartier wrote:
If you know your flonum is within the range of fixnums you can use the very efficient ##flonum->fixnum which will basically compile to a cast (correct me Marc if i'm wrong).
There are several ways to truncate an inexact real to an exact integer. Here are a few I can think of with their execution time on a 2 GHz Intel Core Duo when converting the number 152.97 . The last one is over 230 times faster than the first! Of course they are not completely equivalent because they have different constraints on the argument to convert (some assume the result fits in a fixnum, others in a signed 64 bit exact integer, and the first two have no constraint).
Marc
(define (f0 x) ;; 4600 ns per call (declare (standard-bindings)) (inexact->exact (truncate x)))
(define (f1 x) ;; 4000 ns per call (declare (standard-bindings)) (truncate (inexact->exact x)))
(define (f2 x) ;; 85 ns per call ((c-lambda (double) int64 "___result = ___arg1;") x))
(define (f3 x) ;; 25 ns per call (declare (extended-bindings)) (##c-code "___RESULT = ___FIX(___F64UNBOX(___ARG1));" x))
(define (f4 x) ;; 20 ns per call (declare (extended-bindings) (not safe)) (##fl->fx x))
This brings the following to mind, could provide an additional performance boost (not sure about current cpu architectures, I haven't tested) and possibly even be more correct for what one wants:
http://www.mega-nerd.com/FPcast/
Christian.
On Thu, Oct 30, 2008 at 2:32 AM, Marc Feeley feeley@iro.umontreal.ca wrote:
(define (f0 x) ;; 4600 ns per call (declare (standard-bindings)) (inexact->exact (truncate x)))
(define (f1 x) ;; 4000 ns per call (declare (standard-bindings)) (truncate (inexact->exact x)))
This is *really* interesting w/rt the implementation model of floats. I would guess that this means that inexact->exact just flips an exactness bit in Gambit's float representation, no? I would have thought that truncating an exact rational would be rather expensive in comparison to normalizing a floating integer. I'd think that truncating a float would be relatively cheap.
What's really going on here?
david
On Oct 30, 2008, at 9:33 AM, David Rush wrote:
On Thu, Oct 30, 2008 at 2:32 AM, Marc Feeley feeley@iro.umontreal.ca wrote:
(define (f0 x) ;; 4600 ns per call (declare (standard-bindings)) (inexact->exact (truncate x)))
(define (f1 x) ;; 4000 ns per call (declare (standard-bindings)) (truncate (inexact->exact x)))
This is *really* interesting w/rt the implementation model of floats. I would guess that this means that inexact->exact just flips an exactness bit in Gambit's float representation, no? I would have thought that truncating an exact rational would be rather expensive in comparison to normalizing a floating integer. I'd think that truncating a float would be relatively cheap.
What's really going on here?
I don't quite get Marc's timings; let's look at the expansion:
[descartes:~/Desktop] lucier% cat fix.scm (define (f0 x) ;; 4600 ns per call (declare (standard-bindings)) (inexact->exact (truncate x)))
(define (f1 x) ;; 4000 ns per call (declare (standard-bindings)) (truncate (inexact->exact x)))
(define (test0 n x) (declare (standard-bindings) (extended-bindings) (fixnum) (not safe)) (do ((i 0 (+ i 1))) ((= i n)) (f0 x)))
(define (test1 n x) (declare (standard-bindings) (extended-bindings) (fixnum) (not safe)) (do ((i 0 (+ i 1))) ((= i n)) (f1 x)))
[descartes:~/Desktop] lucier% gsc -keep-c -expansion -cc-options "- save-temps" fix.scm Expansion:
(define f0 (lambda (x) (let ((temp.5 (if (and ('#<procedure #2 ##flonum?> x) ('#<procedure #3 ##flfinite?> x)) ('#<procedure #4 ##fltruncate> x) (truncate x)))) (if ('#<procedure #5 ##fixnum?> temp.5) temp.5 (inexact->exact temp.5)))))
(define f1 (lambda (x) (let ((temp.7 (if ('#<procedure #5 ##fixnum?> x) x (inexact-
exact x))))
(if (and ('#<procedure #2 ##flonum?> temp.7) ('#<procedure #3 ##flfinite?> temp.7)) ('#<procedure #4 ##fltruncate> temp.7) (truncate temp.7)))))
(define test0 (lambda (n x) (letrec ((do-temp.0 (lambda (n x i) (if ('#<procedure #6 ##fx=> i n) #!void (let ((begin-temp.1 (f0 x))) (let ((i ('#<procedure #7 ##fx+> i 1))) (if ('#<procedure #6 ##fx=> i n) #!void (let ((begin-temp.1 (f0 x))) (do-temp.0 n x ('#<procedure #7 ##fx+> i 1)))))))))) (do-temp.0 n x 0))))
(define test1 (lambda (n x) (letrec ((do-temp.2 (lambda (n x i) (if ('#<procedure #6 ##fx=> i n) #!void (let ((begin-temp.3 (f1 x))) (let ((i ('#<procedure #7 ##fx+> i 1))) (if ('#<procedure #6 ##fx=> i n) #!void (let ((begin-temp.3 (f1 x))) (do-temp.2 n x ('#<procedure #7 ##fx+> i 1)))))))))) (do-temp.2 n x 0))))
[descartes:~/Desktop] lucier% gsi Gambit v4.3.0
(load "fix")
"/Users/lucier/Desktop/fix.o2"
(time (test1 1000000 0.2))
(time (test1 1000000 .2)) 2237 ms real time 2218 ms cpu time (2164 user, 54 system) 1265 collections accounting for 1027 ms real time (986 user, 21 system) 400000000 bytes allocated no minor faults no major faults
(time (test0 1000000 0.2))
(time (test0 1000000 .2)) 4523 ms real time 4490 ms cpu time (4359 user, 131 system) 3907 collections accounting for 3122 ms real time (3007 user, 56 system) 1232000000 bytes allocated no minor faults no major faults
*** EOF again to exit [descartes:~/Desktop] lucier% gsi -:m100000 Gambit v4.3.0
(load "fix")
"/Users/lucier/Desktop/fix.o2"
(time (test1 1000000 0.2))
(time (test1 1000000 .2)) 1453 ms real time 1437 ms cpu time (1237 user, 200 system) 3 collections accounting for 3 ms real time (3 user, 0 system) 400000000 bytes allocated no minor faults no major faults
(time (test0 1000000 0.2))
(time (test0 1000000 .2)) 1372 ms real time 1363 ms cpu time (1346 user, 17 system) 12 collections accounting for 11 ms real time (11 user, 0 system) 1232138320 bytes allocated no minor faults no major faults
It appears that once one defines a large enough minimum heap size to basically remove gc time, the largest time hog is the intermodule calls and returns for inexact->exact and truncate. You can see that working with rational numbers adds a lot to the heap allocation.
Brad
On Oct 30, 2008, at 12:04 PM, Bradley Lucier wrote:
[descartes:~/Desktop] lucier% gsi -:m100000 Gambit v4.3.0
(load "fix")
"/Users/lucier/Desktop/fix.o2"
(time (test1 1000000 0.2))
(time (test1 1000000 .2)) 1453 ms real time 1437 ms cpu time (1237 user, 200 system) 3 collections accounting for 3 ms real time (3 user, 0 system) 400000000 bytes allocated no minor faults no major faults
(time (test0 1000000 0.2))
(time (test0 1000000 .2)) 1372 ms real time 1363 ms cpu time (1346 user, 17 system) 12 collections accounting for 11 ms real time (11 user, 0 system) 1232138320 bytes allocated no minor faults no major faults
It appears that once one defines a large enough minimum heap size to basically remove gc time, the largest time hog is the intermodule calls and returns for inexact->exact and truncate. You can see that working with rational numbers adds a lot to the heap allocation.
And yet, with a slightly different argument, f0 is decidedly faster:
[descartes:~/Desktop] lucier% gsi -:m100000 Gambit v4.3.0
(load "fix")
"/Users/lucier/Desktop/fix.o4"
(time (test1 1000000 12.2))
(time (test1 1000000 12.2)) 1361 ms real time 1352 ms cpu time (1156 user, 196 system) 3 collections accounting for 3 ms real time (3 user, 0 system) 400000000 bytes allocated no minor faults no major faults
(time (test0 1000000 12.2))
(time (test0 1000000 12.2)) 990 ms real time 983 ms cpu time (970 user, 13 system) 4 collections accounting for 4 ms real time (4 user, 0 system) 384000000 bytes allocated no minor faults no major faults
This is reproducible. Something strange is going on, I agree.
Brad
On 30-Oct-08, at 1:24 PM, Bradley Lucier wrote:
This is reproducible. Something strange is going on, I agree.
Don't you think this is a consequence of working with different size rationals? Note that on my (32 bit) machine:
% gsi Gambit v4.3.0
(inexact->exact 152.97)
5382153398428631/35184372088832
(inexact->exact 0.2)
3602879701896397/18014398509481984
(inexact->exact 12.2)
3433994715870003/281474976710656
(map fixnum? '(5382153398428631 35184372088832 3602879701896397
18014398509481984 3433994715870003 281474976710656)) (#f #f #f #f #f #f)
Are you on a 64 bit machine where all of these numbers are fixnums?
Marc
On Oct 30, 2008, at 1:39 PM, Marc Feeley wrote:
(map fixnum? '(5382153398428631 35184372088832 3602879701896397 18014398509481984 3433994715870003 281474976710656))
[descartes:~/Desktop] lucier% gsi -:m100000 Gambit v4.3.0
(map fixnum? '(5382153398428631 35184372088832 3602879701896397
18014398509481984 3433994715870003 281474976710656)) (#t #t #t #t #t #t)