我试图在Java中生成100个字符的随机文本。下面是我的代码:
import java.lang.Math;
public class RandomTextGenerator {
public static void main(String[] args) {
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
for (int i = 0; i < 100; i++) {
int a = Math.round(62*Math.random());
int b = a + 1;
System.out.println(characters.substring(a,b));
}
}
我得到错误"Type mismatch: cannot convert from long to intquot;
但是我不明白这个。我明确地将a
和b
声明为int
,而不是long
。我希望我的代码给我一个从0到61的随机整数,所以它不应该自动成为long
,因为0和61都在整数的范围内。
我对Java相当陌生,所以如果我做了一些明显的错误,我很抱歉。
Math.round()在这里返回long值,因此您可以像这样对它进行类型转换,
int A = (int) Math.round(62*Math.random());
另一种方法是(但效率很低)
int A = Long.valueOf(Math.round(62*Math.random())).intValue();
休息,你做得对。:)
这是一种向下转换(可能会发生信息丢失),因此您需要确保右侧的数字仅在int的范围内。
考虑使用java.util.Random类生成随机int
s。
String characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
java.util.Random rand = new java.util.Random();
for (int i = 0; i < 100; i++) {
int a = rand.nextInt(62);
int b = a + 1;
System.out.println(characters.substring(a,b));
}
混合类型影响结果
你说:
我希望我的代码给我一个从0到61的随机整数
你的期望是错误的。
首先在括号内混合类型:(62*Math.random())
。左边是编译器推断的int
。(请参阅Java语言规范中有关文字的内容。)右边是对Math.random()
的调用,文档显示它返回了一个double
。在Java中,当int
乘以double
时会发生什么?结果是一个double
。
然后将double
的值传递给Math.round
。学习Javadoc。您将发现两个名为round
的方法,每个方法采用不同类型的参数。返回不同的类型. 方法Math.round(double a)
返回一个long
,而另一个Math.round
返回一个int
。
你可以通过使你的代码完全简单来避免这种欺骗而不是在一行代码中嵌套操作。您将增量地声明计算中的每个阶段,使您非常了解每个返回值的数据类型。一步一步的结果使您的调试更容易。而且,作为奖励,简单的代码更有可能被编译器高度优化。
同样,当您确定值合适时,您可以调用Math.toIntExact
将long
转换为int
。如果值溢出int
,该方法将抛出异常。因此,如果您的期望被证明是不正确的,您将收到警告。
同样,如果您避免使用幻数,您的代码将更容易理解。使用命名良好的变量/常量。例如,我没有立即理解你的62
乘数是你的字符池的长度。还有一点:这样的号码应该通过调用String#length
进行软编码。
还有一个问题:如果池上的起始位置恰好是池中的最后一个字符,则代码会中断。然后添加一个会使您超过终点,从而导致运行时错误。所以从62
的极限中减去1,得到61
。或者在下面的代码中,( POOL_OF_CHARACTERS.length() - 1 )
.
final String POOL_OF_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
final int DESIRED_LENGTH_OF_RESULTING_TEXT = 100;
StringBuilder stringBuilder = new StringBuilder( "" );
for ( int i = 0 ; i < DESIRED_LENGTH_OF_RESULTING_TEXT ; i++ )
{
double randomProduct = ( ( POOL_OF_CHARACTERS.length() - 1 ) * Math.random() );
long intermediateResult = Math.round( randomProduct );
int startingPositionInPool = Math.toIntExact( intermediateResult ); // Throws an exception if the value overflows an int.
int endingPositionInPool = ( startingPositionInPool + 1 );
String piece = POOL_OF_CHARACTERS.substring( startingPositionInPool , endingPositionInPool );
stringBuilder.append( piece );
}
String randomString = stringBuilder.toString();
System.out.println( "randomString = " + randomString );
运行时。
randomString = 7YqRnJ4TXzMo3nvoUkBRQYq5evOhBjo3I2Cc9fTWAfCFlGY5R4rlFjWqqwRqERkVylXI7le4VLs5nKBHlNuHb03qxFeebDBSsHab
顺便说一下,我会用更方便的ThreadLocalRandom#nextInt( int origin , int bound )
代替Math.random
。注意这个方法是Half-Open的,开头是包容性,结尾是排他性。所以我们不会有任何问题,超越泳池的尽头。我们不需要减去1。
final String POOL_OF_CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890";
final int DESIRED_LENGTH_OF_RESULTING_TEXT = 100;
StringBuilder stringBuilder = new StringBuilder( "" );
for ( int i = 0 ; i < DESIRED_LENGTH_OF_RESULTING_TEXT ; i++ )
{
int startingPositionInPool = ThreadLocalRandom.current().nextInt( 0 , POOL_OF_CHARACTERS.length() ); // Half-Open. The specified bound is exclusive.
int endingPositionInPool = ( startingPositionInPool + 1 );
String piece = POOL_OF_CHARACTERS.substring( startingPositionInPool , endingPositionInPool );
stringBuilder.append( piece );
}
String randomString = stringBuilder.toString();
System.out.println( "randomString = " + randomString );
顺便说一下,只是为了好玩,这里有一个完全不同的方法来完成相同的结果。这种方法使用流和代码点。(在这种情况下不一定更好)
final long DESIRED_LENGTH_OF_RESULTING_TEXT = 100;
int[] poolOfCodePoints = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890".codePoints().toArray();
IntStream positions = new Random().ints( DESIRED_LENGTH_OF_RESULTING_TEXT , 0 , poolOfCodePoints.length );
IntStream codePoints = positions.map( indexIntoCodePoints -> poolOfCodePoints[ indexIntoCodePoints ] );
StringBuilder stringBuilder = codePoints.collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append );
String randomText = stringBuilder.toString();
,或者短:
final long DESIRED_LENGTH_OF_RESULTING_TEXT = 100;
int[] poolOfCodePoints = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz1234567890".codePoints().toArray();
String randomText =
new Random()
.ints( DESIRED_LENGTH_OF_RESULTING_TEXT , 0 , poolOfCodePoints.length )
.map( indexIntoCodePoints -> poolOfCodePoints[ indexIntoCodePoints ] )
.collect( StringBuilder :: new , StringBuilder :: appendCodePoint , StringBuilder :: append )
.toString();