我在Processing中做动画。我正在使用随机点,我需要为立体视觉执行两次代码。 我的代码中有很多随机变量,所以我应该在第二次运行时保存它,或者在我运行程序时重新生成“随机”数字的SAME字符串。 (如此处所说:http://www.coderanch.com/t/372076/java/java/save-random-numbers)
这种方法可行吗?怎么样?如果我将数字保存在txt文件中然后读取它,我的程序会运行得更慢吗?最好的方法是什么?
感谢。
答案 0 :(得分:2)
如果您只需要能够在有限的时间内生成相同的序列,那么使用相同的值为随机数生成器播种以生成相同的序列很可能是最简单,最快捷的方法。只要确保任何并行线程总是以相同的顺序请求它们的伪随机数,否则你将遇到麻烦。
请注意,如果您更新Java VM甚至运行补丁,afaik并不能保证相同的顺序,因此如果您希望长时间存储序列,或者希望能够在Java程序之外使用它,您需要将其保存到文件中。
答案 1 :(得分:1)
以下是一个示例示例:
public static void writeRandomDoublesToFile(String filePath, int numbersCount) throws IOException
{
FileOutputStream fos = new FileOutputStream(new File(filePath));
BufferedOutputStream bos = new BufferedOutputStream(fos);
DataOutputStream dos = new DataOutputStream(bos);
dos.writeInt(numbersCount);
for(int i = 0; i < numbersCount; i++) dos.writeDouble(Math.random());
}
public static double[] readRandomDoublesFromFile(String filePath) throws IOException
{
FileInputStream fis = new FileInputStream(new File(filePath));
BufferedInputStream bis = new BufferedInputStream(fis);
DataInputStream dis = new DataInputStream(bis);
int numbersCount = dis.readInt();
double[] result = new double[numbersCount];
for(int i = 0; i < numbersCount; i++) result[i] = dis.readDouble();
return result;
}
答案 2 :(得分:1)
嗯,有几种方法可以解决这个问题。其中之一是将随机变量保存为文件的输入,并将该文件名作为参数传递给您的程序。
你可以用两种方式之一做到这一点,第一种方法是使用args []参数:
import java.io.*;
import java.util.*;
public class bla {
public static void main(String[] args) {
// You'd need to put some verification code here to make
// sure that input was actually sent to the program.
Scanner in = new Scanner(new File(args[1]));
while(in.hasNextLine()) {
System.out.println(in.nextLine());
}
} }
另一种方法是使用Scanner并从控制台输入读取。它与上面的代码完全相同,但不是Scanner in = new Scanner(new File(args[1]));
而是上面的所有验证码。您将替换Scanner in = new Scanner(System.in)
,但这只是加载文件。
生成这些点的过程可以通过以下方式完成:
import java.util.*;
import java.io.*;
public class generator {
public static void main(String[] args) {
// You'd get some user input (or not) here
// that would ask for the file to save to,
// and that can be done by either using the
// scanner class like the input example above,
// or by using args, but in this case we'll
// just say:
String fileName = "somefile.txt";
FileWriter fstream = new FileWriter(fileName);
BufferedWriter out = new BufferedWriter(fstream);
out.write("Stuff");
out.close();
}
}
这两种解决方案都是用Java读取和写入文件的简单方法。但是,如果您部署这些解决方案中的任何一个,那么您仍然需要对数据进行某种解析。
如果是我,我会去对象序列化,并将我已生成的数据结构的二进制副本存储到磁盘,而不是以低效的方式解析和重新分析该信息。 (通常,使用文本文件会占用更多磁盘空间。)
以下是你将如何做到这一点(在这里,我将重用已经编写过的代码,并在此过程中对其进行评论)Source
你声明了一些包含数据的包装类(顺便说一下,你并不总是这样做。)
public class Employee implements java.io.Serializable
{
public String name;
public String address;
public int transient SSN;
public int number;
public void mailCheck()
{
System.out.println("Mailing a check to " + name
+ " " + address);
}
}
然后,序列化:
import java.io.*;
public class SerializeDemo
{
public static void main(String [] args)
{
Employee e = new Employee();
e.name = "Reyan Ali";
e.address = "Phokka Kuan, Ambehta Peer";
e.SSN = 11122333;
e.number = 101;
try
{
FileOutputStream fileOut =
new FileOutputStream("employee.ser");
ObjectOutputStream out =
new ObjectOutputStream(fileOut);
out.writeObject(e);
out.close();
fileOut.close();
}catch(IOException i)
{
i.printStackTrace();
}
}
}
然后,反序列化:
import java.io.*;
public class DeserializeDemo
{
public static void main(String [] args)
{
Employee e = null;
try
{
FileInputStream fileIn =
new FileInputStream("employee.ser");
ObjectInputStream in = new ObjectInputStream(fileIn);
e = (Employee) in.readObject();
in.close();
fileIn.close();
}catch(IOException i)
{
i.printStackTrace();
return;
}catch(ClassNotFoundException c)
{
System.out.println(.Employee class not found.);
c.printStackTrace();
return;
}
System.out.println("Deserialized Employee...");
System.out.println("Name: " + e.name);
System.out.println("Address: " + e.address);
System.out.println("SSN: " + e.SSN);
System.out.println("Number: " + e.number);
}
}
另一个不需要存储数据的问题的替代解决方案是为任何为您提供随机值的函数创建一个惰性生成器,并且每次都提供相同的种子。这样,您就不必存储任何数据。
然而,这仍然比使用磁盘序列化并将其重新加载更慢一些(我认为)。 (当然,这是一个非常主观的陈述,但我不会列举那些不正确的案例)。这样做的好处是它根本不需要任何类型的存储。
另一种你可能没想过的方法是在你的生成器函数周围创建一个包装器来记忆输出 - 这意味着之前已经生成的数据将从内存中检索出来,而不必是如果相同的输入为真,则再次生成。你可以在这里看到一些资源:Memoization source记住函数调用的想法是节省时间而不会持久化到磁盘。如果一遍又一遍地生成相同的值,这是理想的。当然,对于一组随机点,如果每个点都是唯一的,那么这不会很好地工作,但要记住这一点。
在考虑我在本篇文章中描述的所有先前策略可以组合在一起的方式时,真正有趣的部分就出现了。
设置Memoizer类会很有趣,就像在2的第二页中所描述的那样,然后在该类中实现java.io.Serialization。之后,您可以在memoizer类中添加方法save(String fileName)
和load(String fileName)
,使序列化和反序列化更容易,因此您可以保留用于记忆该函数的缓存。很有用。
无论如何,够了就足够了。简而言之,只需使用相同的种子值,即可生成相同的点对。