给定初始字符和偏移量,在Java中计算字符值

时间:2014-02-09 00:38:55

标签: java math unicode char character

我想生成单个字符串以用作默认标签 - 考虑电子表格应用程序中的列标签。在我的特殊情况下,我只需要在[“A”..“Z”]中的字符串集中绘制,但我正在尝试的解决方案可以应用于小写Latin1字母,数字,希腊字母表中的字符等。

Java中的常见解决方案如下:

static final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

static public char getLabel( int index )
{
    return alphabet.charAt( index );
}

如果index不在[0..25]中,它会相当有效并且会导致运行时错误,但它是典型的Java,因为它很冗长并且需要更多代码来验证它的工作原理正确 - 忘记'U'或用'V'转换等......

相反,我查看了Character类,看看它是否提供了检索序数值的方法 - 或者Unicode索引或数值 - 可以为起始字母返回{{1}然后可以将Unicode块和类别添加到一个整数中,该整数产生一个结果,用于“查找”使用另一个方法所需的字符,该方法将返回'A'给定一个有效的整数值,其中“valid”是依赖于Unicode编码。果然,有一些方法可以做到这一点,而且还有更多。实际上似乎有几种方法可以做同样的事情,有些方法可以使用额外的选项(例如为数值指定基数),然后在试图理解“代码点”之间的差异时产生大的时间差。 “数字值”,“数字”(比方法名称所表示的更复杂),等等。简而言之,char似乎为我的简单要求提供了有用的方法,但包装在一个远远超出的包中我需要做的事情很困难。

最后,可以选择对Character原语进行算术运算。类似的东西:

char
好吧,差不多。在计算结果之前,Java通过将小于assert 'B' == 'A' + 1; 的所有“整数”类型转换为int来使事情变得复杂。由于int被视为整数类型 - 并且是该语言中唯一的无符号整数 - 即使char不是Character而其他问题也会受到相同的转换起来。尽管如此,在必要时通过一些边界检查和转换,Number似乎非常方便,即使它出现了以下示例中提到的问题:

'A' + x

示例代码生成:

class CharTest
{
    static final String alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";

    static public char getLabel( int index )
    {
        return alphabet.charAt( index );
    }

    public static void main( String[] argv )
    {
        System.out.print( "getLabel( 5 ): " );
        System.out.println( getLabel( 5 ) );

        char a = 'A';
        char b = 'B';

        System.out.print( "a: " );
        System.out.println( a );
        System.out.print( "b: " );
        System.out.println( b );
        System.out.print( "++a: " );
        System.out.println( ++a );
        System.out.print( "--a: " );
        System.out.println( --a );
        System.out.print( "a++: " );
        System.out.println( a++ );
        System.out.print( "a--: " );
        System.out.println( a-- );
        System.out.print( "a += 1: " );
        System.out.println( a += 1 );
        System.out.print( "a -= 1: " );
        System.out.println( a -= 1 );
        System.out.print( "a += 5: " );
        System.out.println( a += 5 );
        System.out.print( "a -= 5: " );
        System.out.println( a -= 5 );

        System.out.print( "a + 1: " );
        System.out.println( a + 1 );
        System.out.print( "a - 1: " );
        System.out.println( a - 1 );

        System.out.print( "a + (char) 1: " );
        System.out.println( a + (char) 1 );
        System.out.print( "a - (char) 1: " );
        System.out.println( a - (char) 1 );

        System.out.print( "a + b: " );
        System.out.println( a + b );

        // The casts are just to show intent. I am aware Java will
        // simply add two ints and silently downcast to short.

        short z = (short) 1 + (short) 1;

        System.out.print( "short z = (short) 1 + (short) 1: " );
        System.out.println( z );

        // The same, only different...except the compiler
        // now requires the cast on the right-hand side
        // of the assignment to z or it fails with the
        // following error message:
        //
        //     error: possible loss of precision

        short x = 1;
        short y = 1;

        z = (short) ( x + y );

        System.out.print( "z = (short) ( x + y ): " );
        System.out.println( z );

        // Demonstrate that a is still 'A'. The following tests
        // produce results which indicate it is NUL ('\0') or
        // something even stranger...

        System.out.print( "a: " );
        System.out.println( a );

        // The following will not compile without the explicit
        // casts on the right-hand side of the assignments.
        // This results from converting a, b, and 5 to ints
        // before adding them which produces an int. The error
        // reported by the compiler is:
        //
        //     error: possible loss of precision

        char c = (char) ( a + 5 );

        System.out.print( "char c = (char) ( a + 5 ): " );
        System.out.println( c );

        char d = (char) ( a + b - a );

        System.out.print( "char d = (char) ( a + b - a ): " );
        System.out.println( d );
    }
}

请注意,涉及使用二元运算符的getLabel( 5 ): F a: A b: B ++a: B --a: A a++: A a--: B a += 1: B a -= 1: A a += 5: F a -= 5: A a + 1: 66 a - 1: 64 a + (char) 1: 66 a - (char) 1: 64 a + b: 131 short z = (short) 1 + (short) 1: 2 z = (short) ( x + y ): 2 a: A char c = (char) ( a + 5 ): F char d = (char) ( a + b - a ): B 的表达式需要显式强制转换,而仅使用一元值更新运算符的表达式则不需要。

有没有理由不使用char算法来解决我当前的,相当简单的问题,包括查找已知在Unicode中的特定块内排序的字符?或者,我应该使用索引查找字符串常量,char类提供的方法,还是我在JDK中忽略的另一个更简单的类?

1 个答案:

答案 0 :(得分:0)

AFAIK,你没有忽略任何东西。我认为你已经涵盖了针对特定用例的所有合理方法。

选择归结为:

  • 您是否需要/需要验证index参数,

  • 您是否希望(在某些时候)能够概括此功能;即处理更大的非连续字符范围。

在你的位置,我只是选择更简单的方法,将功能包装为辅助方法,然后转到更重要的问题。 (如果你需要重新审视你的决定,让这个帮助方法简化了事情。)


我不确定您在50道左右的线路测试计划中想要实现的目标,或者为什么要向我们展示。它似乎只是表明Java算术运算符的行为正常: - )


FWIW,我认为你在Character课程等中找不到任何聪明的方法来做这种事情的原因是它们是不必要的。使用标准运算符索引字符串(或char[])或算术可以涵盖所有典型的用例。