在开发应用程序时,我发现了一个严重的错误。但首先是一些细节:我想在GUI上显示温度。温度是双重值。用户应该能够增加/降低温度。目标是模拟加热单元的加热/温度阀。除了具有随机值之外,用户还应该能够通过使用GUI增加/减少该值。基本上,该值在启动时初始化为20.1(只是我在开始时设置的一个随机值)。
当我试图降低温度时,我注意到一种奇怪的行为。当递增时,一切都有效。但降低温度(步长为1)会得到以下结果:20.1,19.1,18.1,17.1,16.1,然后是15.100000000000001,14.100000000000001等。原因是什么?当使用以.1结尾的值时,确实会发生错误。因此,当基数为22.1或31.1时,它并没有什么区别。
错误总是发生在从16.1到15…
它每次都是可复制的。我已经编写了一个测试应用程序,请随意尝试:
package devices;
import java.awt.EventQueue;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class Test extends JFrame {
/**
* the temperature
*/
private Double temp = 20.1;
private JPanel contentPane;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
Test frame = new Test();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Test() {
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 271, 152);
contentPane = new JPanel();
setContentPane(contentPane);
contentPane.setLayout(null);
final JLabel lblNewLabel = new JLabel("");
lblNewLabel.setBounds(10, 11, 235, 56);
lblNewLabel.setFont(new Font("Tahoma", Font.PLAIN, 19));
lblNewLabel.setText(String.valueOf(temp));
contentPane.add(lblNewLabel);
JButton btnNewButton_1 = new JButton("Increase");
btnNewButton_1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
temp = temp + 1;
lblNewLabel.setText(String.valueOf(temp));
}
});
btnNewButton_1.setBounds(10, 78, 101, 23);
contentPane.add(btnNewButton_1);
JButton btnNewButton = new JButton("Decrease");
btnNewButton.setBounds(137, 78, 108, 23);
btnNewButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
temp = temp - 1;
lblNewLabel.setText(String.valueOf(temp));
}
});
contentPane.add(btnNewButton);
}
}
提前问候和感谢,
朱利安0.1在二进制中不是一个整数,所以不能总是按十分位数均匀步进。例子。如果十分之一是您需要的最佳分辨率,那么将它们存储为int
并手动显示它们:
(temp/10).toString() +"."+(temp℅10).toString()
例如,Turbo Pascal就是这么做的。
Double,和其他默认的浮点数表示,是一个无限范围的值的离散表示(两个整数之间有无限的值:1,1.1,1.11,1.11,…2) .
因此,许多值没有精确的表示。
你应该把数字四舍五入到你需要的精度
看这个
[http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html]
则使用BigDecimal而不是Double