• Michael R (unregistered)

    https://xkcd.com/221/

  • Hanzito (unregistered)

    Who could have known that some knowledge of maths would be useful for programmers?

  • (nodebb)

    Question: Doesn't have Java int64 literals like 100000000L ?

  • (nodebb) in reply to MaxiTB

    Yes, of course, the programmer could just have written 10000000000000000L or something.

  • anonymous (unregistered) in reply to MaxiTB

    It does, but I wouldn't expect the author of this code to know that.

  • Jaloopa (unregistered)
    public static Long generateRandomNumberOf(int length) {
        var sb = new StringBuilder();
        var random = new Random();
        for (var i = 0; i < length; i++)
        {
            sb.Append(random.NextInt(0, 9)).ToString();
        }
        return long.Parse(sb.ToString());
    }
    
  • Rob (unregistered) in reply to Melissa U

    Yes, of course, the programmer could just have written 10000000000000000L or something.

    Or more readable: 10_000_000_000_000_000L

  • Rob (unregistered)

    Of course, using the right tools would be too hard...

    private static long getLowerBound(int length) {
        long result = 1L;
        for (int i = 1; i < length; i++) {
            result *= 10;
        }
        return result;
    }
    
    public static long generateRandomNumberOf(int length) {
        // lowerBound will be a 1 followed by (length - 1) zeroes
        long lowerBound = getLowerBound(length);
        // upperBound will be 1 followed by (length) zeroes
        // it's exclusive, so the highest value will be (length) nines
        long upperBound = lowerBound * 10;
        return new SecureRandom().nextLong(lowerBound, upperBound);
    }
    

    And if this requires a Java version < 17, then ThreadLocalRandom can be used instead of SecureRandom, that existed with the nextLong(origin, bound) method since Java 7.

  • Rob (unregistered)

    I've tested my code snippet above. It can generate up to length 24, and can do so in milliseconds at most.

  • (nodebb)

    @Jaloopa: If you're going to iterate, it's faster to keep it in the numeric domain & skip the string munging. Something close to this net of my (uneditable) mistakes:

    public static Long generateRandomNumberOf(int length) {
        long result = 0;
        var random = new Random();
        for (var i = 0; i < length; i++)
        {
            var = var * 10 + random.NextInt(0, 9).ToLong();
        }
        return result
    }
    

    Addendum 2025-11-11 08:31: Seems a few people snuck in above me with similar ideas while I was elsewhere. Sorry to pile-on.

  • (nodebb)

    On a hunch: a lot of copy-pasted instances of this function with a couple of sumbols difference.

  • (nodebb) in reply to Rob

    I'm not sure about this. If Java is similar in it's implementation of randomness with .net then the cryptographic random generators are considerably slower than the regular ones. So using one when there is no business requirement for cryptographic safe randomness is a complete waste of resources.

  • Officer Johnny Holzkopf (unregistered)

    And after a long numb, this function will (maybe) return numb.

  • (nodebb) in reply to Michael R

    In a test suite, the XKCD random number generator is not necessarily a bad option in some circumstances.

    If you want your tests to be repeatable, your random number generator should definitely be deterministic e.g. use a pseudo random number generator with a known seed. In the past, when I've wanted to exercise specific code paths, I've written "random" number generators that merely return successive numbers from a list that I hand crafted.

  • (nodebb) in reply to WTFGuy

    @Jaloopa: If you're going to iterate, it's faster to keep it in the numeric domain & skip the string munging. Something close to this net of my (uneditable) mistakes:

    public static Long generateRandomNumberOf(int length) { long result = 0; var random = new Random(); for (var i = 0; i < length; i++) { var = var * 10 + random.NextInt(0, 9).ToLong(); } return result }

    This returns zero. long result = 0; is set at the top of the method and is never used. I think you meant to cast var as a long and assign it to result?

  • Scragar (unregistered) in reply to WTFGuy

    If they want the random number to have a given length(and no lower) then you can't just do this becauae there's a 1/10 chance the fiest number is 0(even if you fixed your other bugs).

    The best sololution is to simply do something like:

        public static Long generateRandomNumberOf(int length) {
            Long lowerBound = Math.pow(10, length - 1);
            return (long) (Math.random() * 9 * lowerBound + lowerBound);
        }
    

    This guarantees the number is at least 10^(len-1) and at most (10^len)-1 while being very easy to read.

  • (nodebb)

    Here is the fastest random generator for a given length:

    
    var _rnd = new Random();
    long[] _powersOf10 = 
        Enumerable.Range(0, 15).Select(i=> (long)Math.Pow(10, i)).ToArray();
    
    Console.WriteLine(generateRandomNumberOf(5));
    
    long generateRandomNumberOf(int length) 
    {
        long low = _powersOf10[length - 1];
        long high = _powersOf10[length];
        return _rnd.NextInt64(
            low, 
            high
        );
    }
    

    Addendum 2025-11-11 10:02: _rnd can be static or not, it's up to your seeding requirements. _powersOf10 is static readonly - this snippet above was made in sharplab.io, I was lazy to format the code as needed.

  • (nodebb) in reply to Scragar

    See my solution, it's better to cache powers of 10, and .NET has built-in Random.NextInt64 these days. If you have to use Java and it doesn't have something like NextInt64, then your code can be improved to cache the powers, then it's just multiplication and addition.

    Addendum 2025-11-11 10:09: PS. Never mind, just saw Rob's comment, Java does have nextLong, so that's the solution, with cached powers of 10.

  • Anonymous Coward (unregistered)

    The real wtf is that Java doesn't have an easily accesible method of generating a random number of exactly length n. I'm sure there are libs that solve this, but shouldn't it be built in?

  • Anonymous Coward (unregistered)

    The real wtf is that Java doesn't have an easily accesible method of generating a random number of exactly length n. I'm sure there are libs that solve this, but shouldn't it be built in?

  • (nodebb)

    If you are using random numbers in your test, how is that repeatable?

  • (nodebb) in reply to Anonymous Coward

    Generating random numbers of specific decimal length isn't a common scenario compared to generating a random number between a specific lower and upper bound, and generating a specific number of random bytes. Both of these Java does have.

  • (nodebb) in reply to Maia-Everett

    Generating a random integer of length n is equivalent to generating a random integer between 10^(n-1) and 10^n-1. E.g. a 3-digit number is from 100 to 999.

  • blerp (unregistered) in reply to davethepirate

    How is it repeatable? Quite easily. You can use the same random number generator and use the same seed.

  • (nodebb)

    I too work in an industry where random number generation is taken very seriously (to the point where I suspect it's the same one as the OP), and I too would be horrified to come across that code. But I used to test other companies' implementations of RNGs for compliance, and saw a lot of nonsense like this everywhere. If your first thought is ever to use strings to build your random number, just stop. That's not how computers work, that's not how RNGs work, that's just how humans like to look at things. Numbers should be turned into strings for display purposes only.

  • Spike (unregistered)

    So the first digit is less random than the others because it’s guaranteed to never be zero? That seems … problematic?

  • (nodebb) in reply to Mr. TA

    Well, to be fair, this is .net code. So even if you port Java code 1:1 it's on average twice as fast on .net simply because of the different technological stack at play.

  • Alicia Notmyrealname (unregistered)

    I am who sent this code and I'd like to give a bit more context: This was a long time ago and I no longer work there; I am not even in the country anymore, so some details could be a bit foggy in my memory. I see some are already on the right track (as in, how I fixed it). This wasn't really an issue at the time; I just HAD to fix it. The code had been there since the last source control migration, i.e. for ever and nobody seemed to know who wrote it. Nobody seemed to be bothered with me changing it either. There's probably a better way to fix it, but I didn't want to spend much time in this specific function; I was the "new one" and had a bug fix to deliver.

    This was my fix:

         public static long generateRandomNumberOf(int length) {
             final long min = BigInteger.TEN.pow(length - 1).longValueExact(); //from 1 with (length - 1) zeroes
             final long max = BigInteger.TEN.pow(length).longValueExact(); //to 1 with length zeroes
             return min + (long) (Math.random() * (max - min));// exclusive
         }
    

Leave a comment on “Losing a Digit”

Log In or post as a guest

Replying to comment #686951:

« Return to Article