Compression 仅适用于数字的压缩算法

Compression 仅适用于数字的压缩算法,compression,data-compression,Compression,Data Compression,我要压缩位置数据(纬度、经度、日期、时间)。所有的数字都是固定格式的。其中2个(纬度、经度)为十进制格式。其他2个是整数 现在这些数字是固定格式的字符串 以固定格式压缩数字的算法是什么? 仅数字压缩(如果有的话)比字符串压缩好吗? 我应该直接压缩字符串而不将其转换为数字,然后再压缩吗 提前感谢。压缩通常在字节流上工作。当一个流的字节值分布不均匀(例如文本或存储为文本的数字)时,您可以实现的压缩比将更高,因为用于存储更频繁出现的字节的位更少(在Huffman压缩中) 通常,您正在谈论的数据将简单地

我要压缩位置数据(纬度、经度、日期、时间)。所有的数字都是固定格式的。其中2个(纬度、经度)为十进制格式。其他2个是整数

现在这些数字是固定格式的字符串

以固定格式压缩数字的算法是什么? 仅数字压缩(如果有的话)比字符串压缩好吗? 我应该直接压缩字符串而不将其转换为数字,然后再压缩吗


提前感谢。

压缩通常在字节流上工作。当一个流的字节值分布不均匀(例如文本或存储为文本的数字)时,您可以实现的压缩比将更高,因为用于存储更频繁出现的字节的位更少(在Huffman压缩中)

通常,您正在谈论的数据将简单地存储为二进制数(而不是文本),这通常是节省空间和检索效率的


我建议您查看一下压缩的是什么类型的数据?它是如何分发的?有没有订购过?所有这些都会影响它的压缩程度,并且可能允许您将数据转换为更容易压缩的内容,或者直接转换为更小的内容

数据压缩在“随机”数据上效果不佳。如果您的数据在较小的范围内,您很可能能够利用这一点

事实上,您应该简单地尝试运行任何一种常用算法,看看数据是否“足够压缩”。如果不是,并且您对数据的了解比压缩算法“直观”的要多,那么您应该利用这些信息

例如,您的数据不只是Lat和Long,而是假定它们彼此“接近”。然后您可能会存储一个“origin”Lat和Long,其余的可以是differential。也许这些差异小到足以容纳一个带符号的字节


这只是一个简单的例子,说明你可以利用数据知识来做一些事情,而不是一些通用算法可能无法解决的事情。

这是一个小理论很有用的地方。你需要考虑几件事:

  • 您的测量分辨率是多少:0.1°或0.001°?1秒还是1微秒
  • 测量值是按一定顺序关联的,还是随机组合在一起的
比如说,分辨率是0.01°。您知道您的值范围为-180°到+180°,或35900个不同的值。Lg(35900)≈ 16所以你需要16位;14位用于-90°–+90°。显然,如果将这种值存储为浮点值,可以立即将数据压缩一半

与日期时间类似,范围是多少;你必须有多少比特

现在,如果数据是按某种顺序排列的(比如,在一艘船上按顺序采集样本),那么您只需要一个起始值和一个增量;这会有很大的不同。当一艘船以30海里/小时的速度航行时,位置的变化不能超过每小时0.03度或每秒0.0000083度。这些增量将是非常小的值,因此可以将它们存储在非常少的位中

关键是你可以做很多事情,但你必须比我们更了解数据,才能提出建议


更新:哦,等等,定点字符串

好的,这(相对)容易。首先,是的,您希望将字符串转换为某种二进制表示形式。只是组成一个数据项,您可能有

040.00105.0020090518212100Z
你可以转换成

| 4000 | short int, 16 bits | | 10500 | short int, 16 bits | | 20090518212100Z | 64 bits | |4000 |短整数,16位| |10500 |短整数,16位| |20090518212100Z | 64位|
这是96位,12字节对26字节。

这取决于你要对数据做什么,以及你需要多少精度

Lat/long通常以度、分和秒为单位,60秒为一分,60分钟为一度,1度纬度名义上等于60海里(nmi)。1分钟等于1牛顿米,1秒钟刚好超过100英尺

纬度从-90度到+90度。将纬度表示为整数秒,可以得到-324000..+324000的范围,或大约20位。经度为-180到+180,因此以相同的方式表示经度还需要1位

因此,您可以在41位中表示一个完整的横向/纵向位置,至+/-50英尺

显然,如果你不需要那么高的精度,你可以减少你的比特数


请注意,传统的单精度32位浮点使用约24位尾数,因此,如果您仅将lat/long(以秒为单位)转换为浮点,则长度将降至+/-6英尺。对于这种类型的东西,很难打败两个单精度浮点。

根据可用字符的不同,你可以很容易地制作一些东西

例如,如果输入仅为数字(0..9),这里有一个将编码和解码它们的解决方案,使用Kotlin(Java上的类似内容):


您是使用定点还是浮点来表示纵横比?如果有固定数量的位置,则可以将值字节打包到字节数组中。在每个数据包中包含如此少量的数据时,压缩/数据包头中的over header可能比数据本身中的over head更多。还有,你使用的是什么语言?谢谢你的建议。我期待着这样的解决方案。在这里,数据格式是固定的,有数千个顺序数据。所以,我想这里的delta解决方案更有效。问题是,它没有索引。因此,在读取数据之前,必须对其进行解压缩。你能推荐一个更好的索引解决方案吗?非常感谢。我们开始了解数据的真实情况,以及损失是否可以接受。不过有几点想法:每k步存储一个完整值,这样就不必运行
fun encodeDigitsOnlyString(stringWithDigitsOnly: String): ByteArray {
    //we couple each 2 digits together into a single byte.
    //For the last digit, if it has no digit to pair with, it's paired with something that's not a digit
    val result = ArrayList<Byte>()
    val length = stringWithDigitsOnly.length
    var lastDigit: Byte? = null
    for (i in 0 until length) {
        val char = stringWithDigitsOnly[i]
        val digitAsByte = char.toString().toInt().toByte()
        if (lastDigit == null) {
            if (i == length - 1) {
                //last digit
                val newByte = (digitAsByte + 0xf0).toByte()
                result.add(newByte)
            } else {
                //more to go
                lastDigit = digitAsByte
            }
        } else {
            val newByte = (digitAsByte + lastDigit.toInt().shl(4)).toByte()
            result.add(newByte)
            lastDigit = null
        }
    }
    return result.toByteArray()
}

fun decodeByteArrayToDigitsOnlyString(encodedDigitsOnlyByteArray: ByteArray): String {
    val sb = StringBuilder(encodedDigitsOnlyByteArray.size * 2)
    for (byte in encodedDigitsOnlyByteArray) {
        val hex = Integer.toHexString(byte.toInt()).takeLast(2).padStart(2, '0')
        if (hex[0].isLetter())
            sb.append(hex.last())
        else
            sb.append(hex)
    }
    return sb.toString()
}
val inputString="12345"
val byteArray=encodeDigitsOnlyString(inputString) //produces a byte array of size 3
val outputString=decodeByteArrayToDigitsOnlyString(byteArray) //should be the same as the input