Floating over the integers

4

1

As you may know, the typical binary floating point numbers in a computer language are quite different than the typical integer numbers in a computer language. Floating point numbers can represent a much larger range, and can represent fractional amounts, however there is a trade-off that is frequently elided.

The distance between integers is constant, and in fact the value of that constant is one. The distance between floating point numbers, however, is variable, and increases the further one travels down the number line, away from the origin at 0. At some point, that distance is so large that the floating point numbers start skipping over integers, and many integers that are technically less than the maximum value of the floating point numbers, cannot actually be represented by floating point numbers.

The challenge:

Write a program that when given the number n, will print out the first n positive integers that cannot be represented by a floating point number in your language of choice.

  • "First n positive integers" means, lowest in value, closest to the origin, and distinct from each other.

  • Infinite precision floating point numbers are not allowed.

  • It doesn't matter whether you choose 32 bit floats, 64 bits floats, or some other type of float, as long as it is a non-infinite precision floating point number in your language of choice, on your machine of choice.

  • Order of numbers does not matter

  • This is Code Gofl. Smallest number of characters wins.

  • Good luck and have fun

Example:

In Rust, using 32 bit floating point builtin type 'f32':

n=4, result = [16777217,16777219,16777221,16777223]

(updated - 1 order doesnt matter - 2 Golf->Gofl)

don bright

Posted 2019-02-26T05:09:39.520

Reputation: 1 189

Smallest number of characters wins I think you mean bytes. If not, is there a reason you're using characters? – Jo King – 2019-02-26T05:26:36.477

i just love unicode? – don bright – 2019-02-26T05:28:19.537

Do we use single precision floating point or double? – Embodiment of Ignorance – 2019-02-26T06:15:05.570

Could you please remind us how a positive integer is represented as a float? I know I can look it up, but challenges specifications should be self-contained and it would save readers the time. – xnor – 2019-02-26T06:17:21.677

1@xnor I don't think it should include this just because most language use IEEE754 floating point numbers. Other form of floating point numbers should be allowed although I don't know one. – tsh – 2019-02-26T09:03:09.260

2@donbright I recommend scoring in bytes. The reason is that, otherwise, the full code in ASCII-only golfing languages (such as CJam or Pyth) can be compressed in a unicode string that will unpack to the ASCII-only code, therefore saving characters, but not bytes. Furthermore, the byte is the actual unit of digital data storage, while "character" is a term that depends on the encoding the solution uses, and one character can even take up 6 bytes, for example. This is how the "packing" mentioned before worked before we changed the default scoring method for [tag:code-golf] to the byte count. – Erik the Outgolfer – 2019-02-26T20:45:30.087

Do the numbers have to be output in order? Or would your example be valid if it output, for example, [16777223,16777221,16777219,16777217]? – Sara J – 2019-02-26T23:14:22.443

1@Sara-J order does not matter. Updated, thanks. – don bright – 2019-02-26T23:43:27.073

@EriktheOutgolfer sorry, Jo King already used this in their perl answer so I am kind of stuck... . For now i changed it to "Code Gofl" to indicate its not technically Code Golf. – don bright – 2019-02-26T23:56:06.070

@donbright Alright, your call. BTW it's not that code golf is strictly scored in bytes, it was in characters for a long time many years ago, it's just that I recommended scoring in bytes based on my personal experience. – Erik the Outgolfer – 2019-02-27T10:42:41.890

@EriktheOutgolfer yeah i see what you mean... next time ill probably do bytes – don bright – 2019-03-04T01:50:35.247

I don't mind switching my code to score in bytes if you want – Jo King – 2019-03-04T03:09:33.053

Answers

1

cQuents, 9 bytes

&#N_=N+.0

Try it online!

& is broken on TIO right now, so TIO link will not work, but it would time out anyway, as the only way to start at 2^53 is modifing the interpreter.

Explanation

           Implicit input n
&          Output first n terms of the sequence
 #         Only include an integer N in the sequence if:
  N        N
   _=        is not equal to 
     N+.0                    N converted to float

Stephen

Posted 2019-02-26T05:09:39.520

Reputation: 12 293

how can i run this on my machine? i cloned github and typed python cquents.py , pasted the program and got an error – don bright – 2019-02-27T00:09:31.617

@donbright put the code in the source.cq file – Stephen – 2019-02-27T01:49:04.793

python cquents.py \n 5 \n cquents_core.CQSyntaxError: Unknown factor : EOF .... cquents_core.CQSyntaxError: Unknown factor : & – don bright – 2019-02-28T01:39:04.860

@donbright uh you might have a trailing newline in your source.cq file? That would cause that error. If you want to test it without waiting change line 169 in cquents_core.py to self.n = 2 ** 53. – Stephen – 2019-02-28T02:11:12.367

1congratulations, fascinating language – don bright – 2019-03-04T01:46:41.903

3

Perl 6, 28 characters

{grep({.Num+|0-$_},^∞)[^$_]}

Try it online!

This is actually 30 bytes, but the challenge is scored in characters.

This should work theoretically. This creates a lazy list of numbers that compares the default number type (with arbitrary precision) against the same number converted to a Num datatype, which is a 64-bit floating point number, and returns the first \$n\$ elements of the list

Here's a version starting at \$2^{53}-5\$

Jo King

Posted 2019-02-26T05:09:39.520

Reputation: 38 234

1i like the infinity literal. – don bright – 2019-03-04T01:50:00.423

3

C (gcc), 58 bytes

f(n,i){for(i=9;n;i++)i-(int)(i+.0f)&&printf("%d ",i,n--);}

Try it online!

Works with 32-bit float.

nwellnhof

Posted 2019-02-26T05:09:39.520

Reputation: 10 037

2

JavaScript, 46 bytes

n=>{for(x=1n;n;)+[++x]!=x&&console.log(x)&n--}

This will certainly timeout on TIO. So, here is a TIO link which initialize x with 253.


  • Save 7 10 bytes, thanks to Neil.
  • Save 2 bytes, thanks to Arnauld

tsh

Posted 2019-02-26T05:09:39.520

Reputation: 13 072

So sad SpiderMonkey do not support bigint yet. Otherwise we can save many bytes by switching to SpiderMonkey and use print. – tsh – 2019-02-26T09:06:13.917

Number(++x)!=x saves 5 bytes. – Neil – 2019-02-26T09:30:34.173

@Neil I remembered that one cannot mix number with bigint. But I didn't know they can check equality without explicit type convertion.+(++x+'') would be shorter than Number(++x). – tsh – 2019-02-26T09:42:06.393

Would something like this work?

– Oliver – 2019-02-26T16:31:09.177

@Oliver It should work for small n. Try to pass n = 1000 and initial x as 2**54, you will find out the difference. – tsh – 2019-02-27T02:31:56.713

+[++x]!=x saves another 3 bytes. – Neil – 2019-03-01T10:49:28.973

2

Ruby 2.6, 42 bytes

->n{(1..).lazy.select{|i|i!=i*1.0}.take n}

Works with 64-bit floats, returns an enumerator.

Ruby 2.5 and below, 43 bytes

->n{1.step.lazy.select{|i|i!=i*1.0}.take n}

And finally, the one that actually finishes in reasonable time:

->n{(2**53).step.lazy.select{|i|i!=i*1.0}.take n}

Try it online!

Kirill L.

Posted 2019-02-26T05:09:39.520

Reputation: 6 693

cool, i didnt realize ruby could do that – don bright – 2019-03-04T01:49:17.827

2

Java 8, 68 67 bytes

n->{for(int i=9;;)if(++i!=(int)(i+0f))System.out.println(i*n/n--);}

Uses the 32-bit float, but by changing 0f to 0d and int to long it can also be tested with the 64-bit double.

Try it online with int and 0f.
Try it online with long and 0d.

Explanation:

n->{                       // Method with integer parameter and no return-type
  for(int i=9;;)           //  Loop `i` from 9 upwards indefinitely:
    if(++i                 //   Increase `i` by 1 first
          !=               //   And if it does not equal:
            (int)(i+0f))   //   Itself as float, and casted back to integer:
      System.out.println(i //    Print the current `i`
        *n/n--);}          //    And decrease `n` by 1
                           //    (and due to the `n/n`, the infinite loop will stop as soon
                           //     as `n` becomes 0, with a division by zero error)

Kevin Cruijssen

Posted 2019-02-26T05:09:39.520

Reputation: 67 575

1

Python 2, 57 bytes

n=1
exec"while n==int(.0+n):n+=1\nprint n;n+=1\n"*input()

Starting from 1 takes a very long time. For testing purposes, starting at \$2^{53}\$ gives the same results but much quicker: Try it online!

We count up values of n (an integer) until we find one for which converting to a float (by adding .0) and back to an int doesn't result in the same number. We then print that value and go to the next n. An exec loop lets us do this a fixed number of times according to the input.

DLosc

Posted 2019-02-26T05:09:39.520

Reputation: 21 213

1

C# (Visual C# Interactive Compiler), 54 bytes

n=>{for(int i=1;;)if(++i!=(int)(i+0f))Print(i*n/n--);}

Port of Kevin Cruijssen's Java answer

Try it online!

Embodiment of Ignorance

Posted 2019-02-26T05:09:39.520

Reputation: 7 014

1

05AB1E (legacy), 10 bytes

µ¾ÐtnïÊi,¼

No TIO, because it will time out way before it reaches the first number 9007199254740993.. I'm using the legacy, since it is run in Python, so will output the same numbers as the Python answer. I'll see if I can determine the first few numbers for the new version of 05AB1E as well, which is run in Elixir (but that will be a separated answer in that case).

As alternative for the TIO, here a prove that tnï for input 9007199254740993 does not result in 9007199254740993, but in 9007199254740994 instead: Try it online.

Explanation:

µ           # Loop until the counter_variable is equal to the (implicit) input
            # (the counter_variable is 0 by default)
 ¾Ð         #  Push the counter_variable three times
   t        #  Take its square-root
    n       #  And then the square of that
     ï      #  And cast it back from a decimal to an integer
      Êi    #  If they are NOT equal:
        ,   #   Print the counter_variable
         ¼  #   And increase the counter_variable by 1

05AB1E has no builtin to set the counter_variable manually unfortunately, otherwise I would have set it to about 9007199254740000 at the start.

Kevin Cruijssen

Posted 2019-02-26T05:09:39.520

Reputation: 67 575

how can i run o5ab1e legacy version on my own machine? – don bright – 2019-02-28T01:42:03.200

@donbright I'm not entirely sure, but if I look back at the commit history, this commit from July 9th, 2018 was the last commit made in the Python legacy 05AB1E. The commit after that was the start of the Elixir rewrite. So I think you can check out the code from that commit, and then run it with Python with the instructions given in the README of that version.

– Kevin Cruijssen – 2019-02-28T07:23:48.253

@donbright If you need any help, I suggest pinging @Adnan on the 05AB1E chat, since he's the one who made and manages the 05AB1E code (PS: If he doesn't respond, Emigna or Don't be a x-triple dot would probably know as well. I personally primarily use 05AB1E on TIO tbh.)

– Kevin Cruijssen – 2019-02-28T07:24:09.897

thanks. however cquents was one byte shorter. – don bright – 2019-03-04T01:48:21.980