【问题标题】:Can i create a mini int class that only consist of 1, 0, -1?我可以创建一个仅包含 1、0、-1 的迷你 int 类吗?
【发布时间】:2021-10-01 22:11:54
【问题描述】:

我将优化和提高老师为井字游戏提供的代码的性能。由于我将只使用 X = 1、O = -1 和 EMPTY = 0,我不想将这些数字保存在 32 位 int 数组中。我可以像 int 类一样创建我的类,但只有 1、0、-1。我想这样做;

public static final int X = 1, O = -1, EMPTY = 0;
myDataType[][] board = new myDataType[3][3];
board[0][0] = X;
board[0][1] = O;

【问题讨论】:

  • byte 呢?
  • 你能举个例子吗?
  • 我很清楚,基本上你希望一个类有一个 1、0、-1 的 int 值?这意味着该类将有一个字段是 int 值,而没有其他字段?
  • 听起来你想使用枚举
  • 对包装类实例的引用可能会占用更多内存。

标签: java data-structures integer


【解决方案1】:

回答您的问题。假设您可以对数组使用布尔值(带有简单“b”的原始数据类型)。从理论上讲,每个数组元素只需要 1 位。但是根据java文档。 https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html

在 Oracle 的 Java 虚拟机实现中,Java 编程语言中的布尔数组被编码为 Java 虚拟机字节数组,每个布尔元素使用 8 位。

在这种情况下,每个布尔元素需要 8 位。 (这只是为了论证,我们不能使用布尔值,因为它只有真假)

下一个选项是使用 Boolean Boxed 类型。它可以保存值 true、false 和 null

你可以这样映射,

true => 1,
false => -1,
null => 0

并像这样实现它,

 Boolean[][] board = new Boolean[3][3];
    board[0][0] = null;
    board[0][1] = false;
    board[1][0] = true;

结果 Boolean Boxed 类型在内存中占用 128 位。(https://www.baeldung.com/java-primitives-vs-objects)

如果创建自定义类,也会占用更多内存。因此最好使用下面的字节类型,就像大多数建议的那样。

byte[][] board = new byte[3][3];
    board[0][0] = -1;
    board[0][1] = 0;
    board[1][0] = 1;

【讨论】:

    【解决方案2】:

    注意:我并不是说这是一个好主意。但是……


    井字游戏整个棋盘只有 3^9 = 19683 种可能的状态。您可以轻松地将其放入单个 int。作为如何做到这一点的示例,以二进制形式查看它,并将每个 pair 位视为单个单元:

    private int state = 0b00_00_00_00_00_00_00_00_00;
    

    我们可以使用00作为未设置,10作为X和11作为O(01未指定,但也将其称为未设置,这样如果高位为0则未设置) .

    然后我们可以通过简单地将值移动到state 的适当位来获取/设置一个值。在这种情况下:( 3 * row ) + col(对电路板的单元进行编号)然后是 *2,因为我们为每个单元使用 2 位。

    public static final int UNSET = 0b00;
    public static final int X = 0b10;
    public static final int O = 0b11;
    
    public void set( final int row, final int col, final int val ) {
        state |= ( val << index( row, col ) );
    }
    
    public int get( final int row, final int col ) {
        return 0b11 & ( state >>> index( row, col ) );
    }
    
    private static final int index( final int row, final int col ) {
        return 2 * ( ( 3 * row ) + col );
    }
    

    我们使用 OR 来设置特定位的值,并使用 AND 将结果屏蔽为我们感兴趣的两位。在这里进行一些验证可能会很好(检查 rowcol 是在界限内,检查val 是否在0b000b11 之间,在设置之前检查单元格是否未设置,无论其他)。


    有了这个,然后说第一个玩家在中间(X),你的状态是:

    state = 0b00_00_00_00_10_00_00_00_00_00;
    

    然后下一个玩家用 O 进入左上角:

    state = 0b00_00_00_00_10_00_00_00_00_11;
    

    等等


    再一次,我并不是说这是一个好主意,或者对你来说会更快,或者对于快速阅读代码的人来说是可以理解的......但它会将整个板存储在单个 int 中而不是他们的数组:耸耸肩:。

    【讨论】:

    • 注意:您可以使用ternary system 执行此操作并将其存储在short 中。但是如果没有额外的工作来读取值(通过递归除法或8个减法序列),我怀疑这会更慢,因为“获取位移”步骤会复杂得多(没有“trit shift”运算符) .
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-07-20
    • 1970-01-01
    • 2011-01-19
    • 2013-07-22
    • 1970-01-01
    • 1970-01-01
    • 2016-12-21
    相关资源
    最近更新 更多