当前位置: 首页 > 知识库问答 >
问题:

使用素数压缩

解博明
2023-03-14

我想我已经找到了一种方法,可以使用素数进行无损压缩,或者反复使用其他方法。

0-255范围内有54个素数,当我们在字节数组中有素数时,我们可以使用该数的素数索引来存储它,使用6位而不是8位,对吗?

我们需要为每个字节创建一个映射,我们可以存储压缩的数字,并将其html" target="_blank">添加到数据数组中。

起初,这似乎可行,但会略微增加文件大小,但对于LZ4或Huffman之类的算法,会将文件减少为可重新压缩的结构。

索引0-53对应于素数2-251,但有6位的未使用数字。(54-63). 这10个数字也可以用来存储10个不同的非素数,最高频率为6位。所以我们要压缩更多的数字。如果该比率超过50%,我们将能够成功执行压缩。

此外,这种方法可以创造一个重新压缩压缩数字的机会。你认为如果我们在4或8字节的数据块而不是一个字节中创建一个uint和ulong数据类型的方法,我们可以将压缩数据的映射缩小到更小的大小,对吗?

有203280221个小于2^32的素数。这意味着我们可以为每个素数存储28位而不是32位。

通过查看数据数组中素数的比率,我们可以确定是否可以执行有效的压缩。

我认为这种方法不是一种有效的压缩方法,而是一种允许对压缩文件进行重新压缩的数据交换方法。

我想问你知道我们可以用素数做的其他方法吗?因为获得素数非常容易,尤其是对于2^32以下的数字。我们需要在方法中加入素数方法。

共有2个答案

欧阳博超
2023-03-14

你们误会了。我说的是压缩随机数据。如果你把一个文件分成4字节的数据块,每个4字节的数字中10个中有1个是素数。你还应该使用位图来确定每个数字是否是素数。使用位图会明显增加文件的大小,但我认为它可以压缩到32/80以上。因为它有太多的0位。

你可能会说,“这是一个非常有趣的压缩算法。”因为它更压缩大小正在使用其他压缩算法。但是拥有重复压缩过程的能力难道不重要吗?请忽略这种有趣的情况。

一步一步地。首先,让我分享一下我们需要的主要助手代码。

findPrimes()和saveToFile()方法如何在这些代码中更有效?目前,在我的Core i7上可以在大约23分钟内找到最高2^32的质数,并保存在512MB中。然后,您可以从文件中加载质数以供直接使用,而无需重新计算。

using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;

namespace PrimeNumbers {
    public static class PrimeHelper {
        public static IEnumerable<long> FindPrimes (long limit) {
            return (new Primes (limit));
        }

        public static IEnumerable<long> FindPrimes (long start, long end) {
            return FindPrimes (end).Where (pn => pn >= start);
        }

        public static bool IsPrime (this long number) {
            if (number < 2)
                return false;
            else if (number < 4)
                return true;

            var limit = (Int32) System.Math.Sqrt (number) + 1;
            var foundPrimes = new Primes (limit);

            return foundPrimes.IsPrime (number);
        }

        public static bool IsPrime (this int number) {
            return IsPrime (Convert.ToInt64 (number));
        }

        public static bool IsPrime (this short number) {
            return IsPrime (Convert.ToInt64 (number));
        }

        public static bool IsPrime (this byte number) {
            return IsPrime (Convert.ToInt64 (number));
        }

        public static bool IsPrime (this uint number) {
            return IsPrime (Convert.ToInt64 (number));
        }

        public static bool IsPrime (this ushort number) {
            return IsPrime (Convert.ToInt64 (number));
        }

        public static bool IsPrime (this sbyte number) {
            return IsPrime (Convert.ToInt64 (number));
        }
    }

    public class Primes : IEnumerable<long>, IDisposable {
        private long limit;
        private MyBitArray numbers;

        public Primes (long limit) {
            startTime = DateTime.Now;
            calculateTime = startTime - startTime;
            this.limit = limit + 1;
            try { findPrimes (); } catch (Exception e) { Console.WriteLine (e.Message); /*Overflows or Out of Memory*/ }

            calculateTime = DateTime.Now - startTime;
        }

        public Primes (MyBitArray bitArray) {
            this.numbers = bitArray;
            this.limit = bitArray.Limit;
        }

        private void findPrimes () {
            /*
            The Sieve Algorithm
            http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
            */
            numbers = new MyBitArray (limit, true);
            for (long i = 2; i < limit; i++)
                if (numbers[i])
                    for (long j = i * 2; j < limit; j += i)
                        numbers[j] = false;
        }

        public IEnumerator<long> GetEnumerator () {
            for (long i = 2; i < limit; i++)
                if (numbers[i])
                    yield return i;
        }

        IEnumerator IEnumerable.GetEnumerator () {
            return GetEnumerator ();
        }

        // Extended big long number for quickly calculation
        public bool IsDivisible (long number) {
            var sqrt = System.Math.Sqrt (number);
            foreach (var prime in this) {
                if (number % prime == 0) {
                    DivisibleBy = prime;
                    return true;
                }

                if (prime > sqrt)
                    return false;
            }

            return false;
        }

        // For big long number
        public bool IsPrime (long number) {
            return number < limit ?
                this.SingleOrDefault (n => n == number) != 0 :
                !IsDivisible (number);
        }

        public void Dispose () {
            numbers.Dispose ();
        }

        public void SaveToFile (string fileName, SaveOptions saveOptions) {
            int elementSize = 8;

            if ((this.limit - 1L) <= Convert.ToInt64 (byte.MaxValue))
                elementSize = 1;
            else if ((this.limit - 1L) <= Convert.ToInt64 (ushort.MaxValue))
                elementSize = 2;
            else if ((this.limit - 1L) <= Convert.ToInt64 (uint.MaxValue))
                elementSize = 4;

            switch (saveOptions) {
                case SaveOptions.TextFile:
                    saveToTextFile (fileName);
                    break;
                case SaveOptions.BinaryAllNumbersBitArray:
                    saveToFile (fileName, this.Numbers.Bytes);
                    break;
                case SaveOptions.BinaryPrimeList:
                    saveToFile (fileName, this, elementSize);
                    break;
                case SaveOptions.BinaryAllNumbersAndPrimeIndex:
                    saveToFileOnlyIndex (fileName, this, elementSize);
                    break;
                case SaveOptions.All:
                    saveToFile (Path.Combine (Path.GetDirectoryName (fileName), Path.GetFileNameWithoutExtension (fileName) + "_BinaryAllNumbersBitArray.bin"), this.Numbers.Bytes);
                    saveToFile (Path.Combine (Path.GetDirectoryName (fileName), Path.GetFileNameWithoutExtension (fileName) + "_BinaryPrimeList.bin"), this, elementSize);
                    saveToFileOnlyIndex (Path.Combine (Path.GetDirectoryName (fileName), Path.GetFileNameWithoutExtension (fileName) + "_BinaryAllNumbersPrimeIndex.bin"), this, elementSize);
                    saveToTextFile (Path.Combine (Path.GetDirectoryName (fileName), Path.GetFileNameWithoutExtension (fileName) + "_TextFile.txt"));
                    break;

            }
        }

        protected void saveToFile (string fileName, byte[] data) {
            Console.WriteLine ("Saving numbers bits if is prime bit 1 else bit 0...");
            using (MemoryStream mstream = new MemoryStream (data)) {
                ProgressCallback callback = (long position, long total) => { };
                copy (mstream, fileName, callback);
            }
        }

        protected void saveToFile (string fileName, Primes primes, int elementSize = 4) {
            Console.WriteLine ("Saving primes. Element size: {0}...", elementSize);
            using (FileStream file = File.OpenWrite (fileName)) {
                long writed = 0;
                foreach (var prime in primes) {
                    byte[] data = new byte[elementSize];

                    if (elementSize == 8) {
                        data = BitConverter.GetBytes (Convert.ToUInt64 (prime));
                    } else if (elementSize == 4) {
                        data = BitConverter.GetBytes (Convert.ToUInt32 (prime));
                    } else if (elementSize == 2) {
                        data = BitConverter.GetBytes (Convert.ToUInt16 (prime));
                    } else if (elementSize == 1) {
                        data = BitConverter.GetBytes (Convert.ToByte (prime));
                    }

                    file.Write (data, 0, elementSize);
                    writed++;

                    if (writed == 536870912L) {
                        file.Flush (true);
                        writed = 0;
                    }
                }
                file.Close ();
            }
        }

        protected void saveToFileOnlyIndex (string fileName, Primes primes, int elementSize = 4) {
            Console.WriteLine ("Saving all numbers prime indexes if not prime index is -1. Element size: {0}...", elementSize);
            using (FileStream file = File.OpenWrite (fileName)) {
                int index = 0;
                long writed = 0;
                long length = Convert.ToInt64 (uint.MaxValue) + 1L;
                for (long i = 0; i < length; i++) {
                    byte[] data = new byte[elementSize];

                    if (elementSize == 8) {
                        if (primes.Numbers[i]) {
                            index++;
                            data = BitConverter.GetBytes (Convert.ToInt64 (index));
                        } else {
                            data = BitConverter.GetBytes (Convert.ToInt32 (-1));
                        }
                    } else if (elementSize == 4) {
                        if (primes.Numbers[i]) {
                            index++;
                            data = BitConverter.GetBytes (Convert.ToInt32 (index));
                        } else {
                            data = BitConverter.GetBytes (Convert.ToInt32 (-1));
                        }
                    } else if (elementSize == 2) {
                        if (primes.Numbers[i]) {
                            index++;
                            data = BitConverter.GetBytes (Convert.ToInt16 (index));
                        } else {
                            data = BitConverter.GetBytes (Convert.ToInt16 (-1));
                        }
                    } else if (elementSize == 1) {
                        if (primes.Numbers[i]) {
                            index++;
                            data = BitConverter.GetBytes (Convert.ToSByte (index));
                        } else {
                            data = BitConverter.GetBytes (Convert.ToSByte (-1));
                        }
                    }

                    file.Write (data, 0, elementSize);
                    writed++;

                    if (writed == 536870912L) {
                        file.Flush (true);
                        writed = 0;
                    }
                }
                file.Close ();
            }
        }

        public delegate void ProgressCallback (long position, long total);
        protected void copy (Stream inputStream, string outputFile, ProgressCallback progressCallback) {
            using (var outputStream = File.OpenWrite (outputFile)) {
                int writed = 0;
                const int bufferSize = 65536;
                while (inputStream.Position < inputStream.Length) {
                    byte[] data = new byte[bufferSize];
                    int amountRead = inputStream.Read (data, 0, bufferSize);
                    outputStream.Write (data, 0, amountRead);

                    writed++;

                    if (progressCallback != null)
                        progressCallback (inputStream.Position, inputStream.Length);

                    if (writed == 32768) {
                        outputStream.Flush (true);
                        writed = 0;
                    }
                }
                outputStream.Flush (true);
            }
        }

        protected void saveToTextFile (string fileName) {
            Console.WriteLine ("Saving primes to text file...");
            using (System.IO.StreamWriter file =
                new System.IO.StreamWriter (fileName)) {
                long writed = 0;
                foreach (var prime in this) {
                    file.WriteLine (prime.ToString ());

                    if (writed == 536870912L) {
                        file.Flush ();
                        writed = 0;
                    }
                }

                file.Close ();
            }
        }

        private static DateTime startTime;
        private static TimeSpan calculateTime;
        public TimeSpan CalculateTime { get { return calculateTime; } }
        public long DivisibleBy { get; set; }
        public long Length { get { return limit; } }
        public MyBitArray Numbers { get { return numbers; } }
    }

    public class MyBitArray : IDisposable {
        byte[] bytes;
        public MyBitArray (long limit, bool defaultValue = false) {
            long byteCount = Convert.ToInt64 ((limit >> 3) + 1);
            this.bytes = new byte[byteCount];
            for (long i = 0; i < byteCount; i++) {
                bytes[i] = (defaultValue == true ? (byte) 0xFF : (byte) 0x00);
            }
            this.limit = limit;
        }

        public MyBitArray (long limit, byte[] bytes) {
            this.limit = limit;
            this.bytes = bytes;
        }

        public bool this [long index] {
            get {
                return getValue (index);
            }
            set {
                setValue (index, value);
            }
        }

        bool getValue (long index) {
            if (index < 8) {
                return getBit (bytes[0], (byte) index);
            }

            long byteIndex = (index & 7) == 0 ? ((index >> 3) - 1) : index >> 3;
            byte bitIndex = (byte) (index & 7);
            return getBit (bytes[byteIndex], bitIndex);
        }
        void setValue (long index, bool value) {
            if (index < 8) {
                bytes[0] = setBit (bytes[0], (byte) index, value);
                return;
            }

            long byteIndex = (index & 7) == 0 ? (index >> 3) - 1 : index >> 3;
            byte bitIndex = (byte) (index & 7);

            bool old = getBit (bytes[byteIndex], bitIndex);

            bytes[byteIndex] = setBit (bytes[byteIndex], bitIndex, value);
        }

        bool getBit (byte byt, byte index) {
            return ((byt & (1 << index)) >> index) == 1;
        }

        byte setBit (byte byt, byte index, bool value) {
            return (byte) ((byt & ~(1 << index)) + (value ? 1 << index : 0));
        }

        public void Dispose () {
            GC.Collect (2, GCCollectionMode.Optimized);
        }

        private long limit;
        public long Limit { get { return limit; } }
        public byte[] Bytes { get { return this.bytes; } }
    }

    public enum SaveOptions {
        All,
        TextFile,
        BinaryAllNumbersBitArray,
        BinaryPrimeList,
        BinaryAllNumbersAndPrimeIndex
    }
}
任云瀚
2023-03-14

一种高效实用的32位素数压缩方法是使用简单的8位字节存储连续素数之间减半的差值(并在需要时从稀薄的空气中提取素数2)。通过一点索引魔术,这提供了超快的“解压”——即,当需要在素数范围上迭代时,它是一种理想的表示形式,因为它比普通素数使用更少的内存。

低于2^32的203280220奇数素数需要相应的字节数,即小于194 MB的位。字节大小减半的差异的可用性扩展到304599508537(大约2^38),但从那以后,有必要发明一种方案来编码大于510的偶然间隙。然而,当存储间隙索引而不是将间隙宽度减半时,该方案几乎可以永远持续下去(参见Prime gap article@Wikipedia)。

这些连续差异块可以使用常用的zlib stile压缩或类似压缩进行进一步压缩,在这种情况下,压缩效果比压缩压缩的仅占优势的位图或mod 30轮子时更好。这可以用作磁盘上的压缩表示。

然而,请注意,一个mod 30轮子只需要136 MB,而且它是可直接索引的,就像满足素性查询一样。提取(解码)素数范围比delta编码的素数慢很多,但仍然比重新筛选素数快。因此,使用mod 30 wheel存储素数是“压缩”素数的最有效方法之一,可以使素数直接可用。

混合形式也可以非常成功。例如,当从mod 30轮解码质数时,您可以直接以增量编码形式存储它们,而无需将它们具体化为数字向量。这可以被视为一种重新压缩的形式。mod 30轮将是磁盘和主存储器格式,增量编码将是某些查询结果的交换格式。

增量编码和轮式存储有一个重要的优点:它们的存储需求基本上独立于所表示素数的大小。相反,如果将素数存储为数字,则会得到对数增长的存储需求。一、 64位素数占用的空间是16位素数的四倍。

关于质数轮的解释可以在维基百科文章Wheel Factoriation中找到。

下表显示了当向轮子添加越来越多的素数时所得到的空间减少,这两种素数都是相对于未翻转表示(“比率”)和相对于前一步(“增量”)。“辐条”列给出了每个车轮旋转的潜在主要轴承辐条(残余物)的数量,这让您了解了优化、完全展开实现的复杂性——la Kim Walisch的primesieve。正如你所见,在复杂性爆炸的同时,收益正在迅速减少。

wheel mod 2(也称为概率筛)很重要,因为它几乎不需要任何代码复杂度方面的成本,就能为您带来最大的成功。当操作赔率筛选时,mod 3车轮的大部分速度优势几乎可以通过手动技巧(索引技巧)轻松获得。wheel mod 30很重要,因为它在代码复杂度和加速之间提供了良好的平衡,这使其成为优化实现的理想目标。高达mod 30030的控制盘已在实际实施中使用,但与mod 30控制盘相比,增益实际上可以忽略不计,而增加的复杂性和性能损失则没有。在大学校园中,在特殊项目的背景下,甚至可以看到更高阶的轮子。

金·瓦利什(Kim Walisch)的筛子程序在网络上任何地方都是最快的,原因之一是他实现了mod 30车轮8个可能跨步序列中每个序列的展开版本,每个序列的8个可能阶段中的每个都有特定的回路入口点。所有这些都是用唯一一种语言(C/C)实现的,您可以获得真正名副其实的优化编译器。

对车轮mod 210的48个残基做同样的事情将意味着36倍的代码(!),而位图大小的减少可以忽略不计。但是,mod 210和mod 2310可能是代码生成器(C/C代码或. NET IL)的有前途的目标,如果您有几个月的空闲时间可以燃烧的话。

 类似资料:
  • 对于不知道DICOM文件是什么的人来说,它是一个保存着关于病人的医学成像数据的文件。它保存着患者数据和一些像素数据。您只需要知道像素数据在同一文件中,但与患者的其余数据分离。 我做了一个程序,可以读取DICOM文件中的原始像素数据。然而,像素数据经常使用JPEG压缩进行压缩。下面是我用来了解像素压缩方法的字典: 如您所见,有26种不同类型的JPEG压缩方法需要解压(所有这些方法的键都是1.2.84

  • 问题内容: 有人可以向我解释zlib库在Nodejs中如何工作吗? 我对Node.js很陌生,还不确定如何使用缓冲区和流。 我的简单情况是一个字符串变量,我想将字符串压缩或解压缩(压缩或膨胀,gzip或gunzip等)到另一个字符串。 即(我希望它如何工作) 感谢您的帮助:) 问题答案: 更新 :没意识到在节点0.5中有一个新的内置“ zlib”模块。我在下面的答案是针对第三方node- zlib

  • 我有一个学校作业,要求我接受一个输入流,并使用apache commons压缩库将其压缩成一个字节数组,格式有5种(根据用户规范)。这5种格式是:ZIP、JAR、SEVENZ、BZIP2和gzip。我编写了以下方法以JAR格式压缩输入流,但得到了一个带有字符串“no current entry”的illegalStateException。

  • 我得到无效的zip,当写入文件以下代码: 我将其写入文件的方式是: 我做错了什么?

  • 本文向大家介绍php使用ZipArchive函数实现文件的压缩与解压缩,包括了php使用ZipArchive函数实现文件的压缩与解压缩的使用技巧和注意事项,需要的朋友参考一下 PHP ZipArchive 是PHP自带的扩展类,可以轻松实现ZIP文件的压缩和解压,使用前首先要确保PHP ZIP 扩展已经开启,具体开启方法这里就不说了,不同的平台开启PHP扩增的方法网上都有,如有疑问欢迎交流。这里整

  • 请务必理解如下章节后阅读此章节: 安装 Node 和 gulp 使用 gulp 压缩 JS 访问论坛获取帮助 压缩 css 代码可降低 css 文件大小,提高页面打开速度。 我们接着将规律转换为 gulp 代码 规律 找到 css/ 目录下的所有 css 文件,压缩它们,将压缩后的文件存放在 dist/css/ 目录下。 gulp 代码 你可以 下载所有示例代码 或 在线查看代码 当熟悉 使用 g