Programming 01

首先通过README.md,很容易发现任务列表只有3个:

  • DEC.INT to BIN.COMPLEMENT
  • DEC.INT to BCD.W8421
  • DEC.FLOAT to BIN.FLOAT

问题很清楚,本质上只是一个进制转换的需求。但是进一步查看他预先写好的代码发现,rtw约定了一个{@code}作为中间转换格式,在TransformFactory.java中的一系列 if中不难发现这一个{@code}是一个储存了一个二进制串的Transformer类,然而这一点为后续的TestUnit.java测试带来了巨大的麻烦(后面会提到),我们所需要做的就是补全代码中的若干个//TODO


初期工作

  1. DEC.INT to BCD.W8421

    首先弄清楚什么是W8421,简单来说就是用4位二进制来表示单个0~9的数字,那么问题就很简单了,把String形式的@code里的数字一个个提取出来,通过char to int,再由int to binary转换成4位二进制码。
    难点有几个,首先是Integer.toBinaryString()这个方法,把int转换成二进制字符串,这个串有个特点,除非该int为0,否则对于非负数而言,二进制串必定以1开头,也就是去掉了前导0,那么问题来了,0~9显然有部分数字不足4位二进制,我们就需要格式化填充0,这里我们容易想到.format()的格式化方法,即类似C输出的格式,但要注意的是这里我们要填充的是字符串,因而需要一定的转换,代码如下

    StringBuilder ret=new StringBuilder(code.charAt(0)=='-'?"1101":"1100"); //约定符号位
    int i=0; code=code.replace("-","");
    if(code.length()>7)
        code=code.substring(code.length()-7,code.length()); //处理溢出
    for(i=0;i<7-code.length();i++)
        ret.append("0000");          //填充足够的长度
    i=0;
    while(i<code.length())
        ret.append(String.format("%4s",Integer.toBinaryString(code.charAt(i++)-'0')).replace(" ","0")); //格式化4位
    

    可以看到这个任务很简单,只是十进制之间的表示转换。

  2. DEC.INT to BIN.COMPLEMENT

    这一部分的任务就是十进制串转二进制补码,直观的初步思路就是判断一下是否为负数,正数直接toBinaryString(),负数则加一步取反加1,然而这地方却踩坑了...大数的溢出问题,于是出于通用性的考虑,直接使用BigDecimal来处理

    boolean flag=(code.charAt(0)=='-');
    StringBuilder tmp=new StringBuilder();
    String ret=""; String ad="";
    BigDecimal ans=new BigDecimal(code.replace("-","")); //去除符号
    while(ans.compareTo(new BigDecimal("0"))==1){
        tmp.append(ans.remainder(new BigDecimal("2")).toString()); //简单处理出一个二进制串
        ans=ans.divideToIntegralValue(new BigDecimal("2"));
    }
    tmp=tmp.reverse(); ret=tmp.toString();
    

    这一步可以得出tmpret是我们暂时得出的无符号二进制串,如果非负则无需处理,只需要在前面补0,或者处理溢出即可,代码如下<a name="divtop"> </a>

    if(ret.length()<=32) {
        for (int i = 1; i <= 32 - ret.length();i++)
        ad=ad.replaceFirst("",flag?"1":"0");
    }else{
         ret=ret.substring(ret.length()-32,ret.length());
    }//后续会在这里删除这个else语句
    

    如果是负数,那么flag==true,这里用到了课上加法器的一些技巧,即位数s[i]=c^s[i],进位c=c&s[i],为了处理方便,多使用一个字符数组来作运算

    if(flag) {
       ret=tmp.insert(0,"00").toString();  //添加两位处理符号位进位的溢出
       ret=ret.replace("0","2").replace("1","0").replace("2","1"); //很蠢的取反操作...
       char[] status=ret.toCharArray();
       for(int i=ret.length()-1,jud=1;i>=0;i--){
        status[i]=(char)((jud^(ret.charAt(i)-'0'))+'0');
        jud=((ret.charAt(i)-'0')&jud);
       }
       ret= Arrays.toString(status).replaceAll("[\\[\\]\\s,]", "");
    }
    
  3. DEC.FLOAT to BIN.FLOAT

    这一个部分没有什么特别好的技巧,处理正负号后,先处理整数部分,判断是否为0,记住整数部分二进制串的位数dotloc,再将小数部分转成float(暂时只想到这个方法,否则只能手动模拟小数乘法了...),不断乘2来得到小数点后的二进制串,然后找到第一个前导1,这里要利用前面记录的dotloc判断一下指数大小,如果溢出则要转换为前导0,然后根据IEEE标准进行填充就好了<a name="divd"> </a>

    StringBuilder ret=new StringBuilder(code.charAt(0)=='-'?"1":"0");
    String[] parts=code.split("\\."); //后续有新增的部分代码
    StringBuilder temp=new StringBuilder(Integer.toBinaryString(Integer.valueOf(parts[0].replace("-",""))));
    int dotloc=(temp.charAt(0)=='0'?0:temp.length());
    float remain=Float.valueOf("0."+parts[1]);
    while(remain!=0){
        remain*=2;
        if(remain>=1){
         temp.append("1");
             remain-=1;
        }else{
         temp.append("0");
        }
    }
    if(dotloc==0){
     dotloc=127-(temp.indexOf("1")==-1?temp.indexOf("1"):127);
     if(dotloc<0)dotloc=0;
    }else{
     dotloc=126+dotloc;
    }
    ret.append(String.format("%"+eLength+"s",Integer.toBinaryString(dotloc)).replace(" ","0"));
    ret.append(String.format("%-"+sLength+"s",temp.substring(1)).replace(" ","0"));
    

后期处理 Test

  • TestUnit.java这个文件中构建的判断方法是往哈希表中添加准备好的答案对,枚举key值调用number.get()方法,与存好的value进行比对,但这里就是他的坑所在,观察代码可知,往哈希表中添加答案对时,即使是DEC.INT或BCD.W8421, 也会添加额外的DEC.FLOAT,而原来的TransformFactory.java中应该对此反应的部分if(rawType.equals(PresentType.BCD.W8421))下注释了//nothing to do,如果按他的注释补充代码会导致对部分样例的调用毫无反应,因此,本着样例驱动编程原则,在这里面补充了代码

    String ret="";
    if(Pattern.matches("^1101[0-9]*",code)){
        ret="-";
    }
    boolean flag=false;
    Pattern p=Pattern.compile("\\d{4}");
    Matcher m=p.matcher(code.substring(4,code.length()));
    for(int i=0,j=0;i<7;i++){
        if(m.find())
            j=Integer.parseInt(m.group(),2);
        if(j==0) {
            if (!flag) {
                continue;
            }
        }else{
            flag=true;
        }
        ret = ret + String.valueOf(j);
    }
    

    同时,在处理这个问题时,突然想到了另外的坑,如果按原来的{@code}约定为二进制码,那么在处理大数时会丢失精度,是否应该采用十进制字符串作为中间格式?

  • 后续在BinTest.javaDecimalTest.java中都存在一些问题而没有通过,还没来得及设断点去研究具体原因,但估计与前面的类似,number.get()方法对某些类型转换无反应(因为对应的if没有写),作业的DDL在9月30日,近日再进行测试。


后续Debug

  • BinTest.java(2019/9/25)

    观察样例可以发现,这里面的数据Number生成全是eq(PresentType.BIN.TWOS_COMPLEMENT,PresentType.BIN.TWOS_COMPLEMENT,...),再回到我们的TransformFactory.java中发现,在if(rawType.equals(PresentType.BIN.TWOS_COMPLEMENT))下方rtw给出了注释//nothing to do,所以说真的我很想骂人,这个项目构建的框架就非常奇怪,根本不应该用二进制作为中间形式,这一串字符串里面的01电脑也看不懂啊,还会溢出,为什么不直接就十进制保存了,还方便我们直接做to(type)这个方法???

    这么缝缝补补首先导致了代码量变多,但是也没有办法,硬着头皮补吧,还能咋办?

    这里得考虑把int形式的二进制补码字符串转成十进制字符串,由于有负数,然而valueOf()parseInt()都只能解析正的radix:2,所以想到了前边我们做过的取补码操作,模块化一下,写成一个静态方法吧

    public static String getComplement(String tar){
        tar=tar.replace("0","2").replace("1","0").replace("2","1");
        char[] status=tar.toCharArray();
        for(int i=tar.length()-1,jud=1;i>=0;i--){
            status[i]=(char)((jud^(tar.charAt(i)-'0'))+'0');
            jud=((tar.charAt(i)-'0')&jud);
        }
        return Arrays.toString(status).replaceAll("[\\[\\]\\s,]", "");
    }
    

    然后就是喜闻乐见的直接用轮子了<a name="divm"> </a>

    boolean flag=(code.charAt(0)=='1');
    if(flag){
        code='1'+code;
        code=getComplement(code);
    }
    int dec=Integer.parseInt(code,2);
    if(flag){
        dec=-dec;
    }
    return TransformerFactory.getTransformer(PresentType.DEC.INTEGER,storageType,Integer.toString(dec)); //能进入这个if语句说明已经转换过一次,后续需要其他的type就要调用getTransformer通过十进制传递数值来转换
    

    于是按下test的运行按钮发现过了两个样例,第三个报错而且是红色报错,定睛一看发现他这是巨坑,嵌套了一层Number的生成,本质上是从int的二进制补码转换成十进制的小数,然后用这个输出的字符串作为参数,最后又转换成int的二进制补码,也就是绕了一圈。但这其中有一个问题:十进制小数怎么转成int形式的二进制补码??可以直接说:这个问题没有任何实际意义,因为小数要转成二进制补码的前提当然是这个小数是.0结尾的,更何况在这里的这个小数还是我们从二进制补码转成十进制再加上".0"生成出来的,所以在这里我们需要把.0给删掉,于是乎又是缝缝补补(加if语句,这是特例情况,这种条件下小数部分为0),附上代码

    boolean flag=(code.charAt(0)=='1');
    int exp=Integer.parseInt(code.substring(1,9),2)-127; //exp>=0
    int ret=Integer.parseInt("1"+code.substring(9,9+exp),2); //记得加上前导1
    if(flag){
        ret=-ret;
    }
    return TransformerFactory.getTransformer(PresentType.DEC.INTEGER,storageType,Integer.toString(ret));
    

    于是通过样例编程法,BinTest.java成功通过。

  • DecimalTest.java(2019/9/26)

    首先发现在DecimalTest.java之中前面的几个testInteger()只有一个出现错误,看了数据发现这是之前我们所提到过的大数溢出问题,简单来说就是我们截取了一定的位数,导致回转十进制转成小数时,数据出错。解决方法的话一开始考虑在判断溢出时,特判一下转换需求,如果要立即转成补码则不转换,但这存在一个问题,我们的代码逻辑无法判断这个需求是不是“立即”的。换一个思路,考虑是否能将补码完整保存,最终在Transformer.to()中再进行截取。具体来说

    前面的代码之中else部分的语句可以移动到Transformer.to()方法,因此变成了

    public String to(PresentType type) {
        Transformer tmp=TransformerFactory.getTransformer(this.type,type,code);
        if(tmp.code.length()>32) {
            return tmp.code.substring(tmp.code.length()-32,tmp.code.length());
        } else{
            return tmp.code;
        }
    }
    

    但运行时发现又报错了,原因是在传回这个超过32位的之后,之前的parseInt()方法超出了解析范围,所以应该在此之前特判一下,在根据正负取补码之后加一个if语句

    if(code.length()>32){
        BigDecimal tmp=new BigDecimal("0");
        BigDecimal record=new BigDecimal("1");
        for(int i=code.length()-1;i>=0;i--) {
            if(code.charAt(i)=='0'){
                record=record.multiply(new BigDecimal("2"));
            }
            tmp = tmp.add(record);
            record=record.multiply(new BigDecimal("2"));
        }
        code=tmp.toString();
        return TransformerFactory.getTransformer(PresentType.DEC.INTEGER,storageType,flag?"-"+code:code);
    }
    

    但仍然报错,仔细看不难看出是传入这个大数的小数形式code+".0"时报错了,同时去看样例对应的值,是"11111111100000000000000000000000",也就是负无穷,所以我们在这里多加一个if判断十进制下的位数与符号就可以了。在这里我们考虑到如果十进制数在补码形式下都已经溢出的话,通过加.0的小数位转换成小数,乃至小数的二进制表示都是无意义的,因此只要判断是否大于Integer.MAX_VALUE即可

    boolean flag=(code.charAt(0)=='-');
    code=code.replace("-","");
    StringBuilder ret=new StringBuilder(flag?"1":"0");
    String[] parts=code.split("\\.");
    if(new BigDecimal(parts[0]).compareTo(new BigDecimal(Integer.MAX_VALUE))==1){
        return new Transformer(PresentType.BIN.FLOAT,ret.append("1111111100000000000000000000000").toString());
    }
    

    再点击运行Test,发现成功通过,而后面还剩下几个TestFloat()有错误,但今天课上老师说这整道题被助教写得太复杂了,要更新一个原意写出来的简单版本,因此我就不再继续样例编程法通过看后面的刁钻的输入的断点来改代码了,因为实在太麻烦了,等待后续更新之后,直接粘贴这个项目的代码应该就可以AC了。


新版Programming(2019/9/26)

打开文件,发现文件的结构也太简单了,就3个相互转化,一共是6个方法待写,整数和NBCD部分我们很容易就可以粘贴上去,这部分代码如下

public static String getComplement(String tar){
    tar=tar.replace("0","2").replace("1","0").replace("2","1");
    char[] status=tar.toCharArray();
    for(int i=tar.length()-1,jud=1;i>=0;i--){
        status[i]=(char)((jud^(tar.charAt(i)-'0'))+'0');
        jud=((tar.charAt(i)-'0')&jud);
    }
    return Arrays.toString(status).replaceAll("[\\[\\]\\s,]", "");
} //取补码
public String intToBinary(String numStr) {
    boolean flag=(numStr.charAt(0)=='-');
    StringBuilder tmp=new StringBuilder();
    String ret="";
    String ad="";
    BigDecimal ans=new BigDecimal(numStr.replace("-",""));
    while(ans.compareTo(new BigDecimal("0"))==1){
        tmp.append(ans.remainder(new BigDecimal("2")).toString());
        ans=ans.divideToIntegralValue(new BigDecimal("2"));
    }
    tmp=tmp.reverse();
    ret=tmp.toString();
    if(flag) {
        ret=tmp.insert(0,"00").toString();
        ret=getComplement(ret);
    }
    if(ret.length()<=32) {
        for (int i = 1; i <= 32 - ret.length();i++)
            ad=ad.replaceFirst("",flag?"1":"0");
    }
    return ad+ret;
}//十进制整数转二进制补码
public String binaryToInt(String binStr) {
    boolean flag=(binStr.charAt(0)=='1');
    if(flag){
        binStr='1'+binStr;
        binStr=getComplement(binStr);
    }
    int dec=Integer.parseInt(binStr,2);
    if(flag){
        dec=-dec;
    }
    return Integer.toString(dec);
}//二进制补码转十进制整数
public String decimalToNBCD(String decimal) {
    StringBuilder ret=new StringBuilder(decimal.charAt(0)=='-'?"1101":"1100");
    int i=0;
    decimal=decimal.replace("-","");
    if(decimal.length()>7){
        decimal=decimal.substring(decimal.length()-7,decimal.length());
    }
    for(i=0;i<7-decimal.length();i++)
        ret.append("0000");
    i=0;
    while(i<decimal.length()){
        ret.append(String.format("%4s",Integer.toBinaryString(decimal.charAt(i++)-'0')).replace(" ","0"));
    }
    return ret.toString();
}//十进制整数转W8421
public String NBCDToDecimal(String NBCDStr) {
    //TODO:
    String ret="";
    if(Pattern.matches("^1101[0-9]*",NBCDStr)){
        ret="-";
    }
    boolean flag=false;
    Pattern p=Pattern.compile("\\d{4}");
    Matcher m=p.matcher(NBCDStr.substring(4,NBCDStr.length()));
    for(int i=0,j=0;i<7;i++){
        if(m.find())
            j=Integer.parseInt(m.group(),2);
        if(j==0) {
            if (!flag) {
                continue;
            }
        }else{
            flag=true;
        }
        ret = ret + String.valueOf(j);
    }
    return  ret; //后续有更改
}//W8421转十进制整数

提交之后发现都过了,除了有一个样例是NBCDToDecimal报错了,考虑到唯一可能的bug应该是全是0的情况,特判一下再看看结果,把return ret;改成return flag?ret:ret+"0";然后发现成功过掉了这个样例,接下来就是魔改Float这一块了。


  1. 先看README.md文件

    1. public String floatToBinary(String floatStr)

      将浮点数字面值转化成32位单精度浮点数表示

      • 负数以"-"开头,正数不需要正号
      • 考虑正负无穷的溢出("+Inf", "-Inf",见测试用例格式)
    2. public String binaryToFloat(String binStr)

      将32位单精度浮点数表示转化成浮点数字面值

      • 特殊情况同上

    从前面来看个新作业的样例强度应该不是特别大,所以问题集中在这个"+Inf"与"-Inf"上面,在这里贴一下IEEE-754标准以便于理解

    类别 正负号 实际指数 偏移后的指数 指数域 尾数域 数值
    0 -127 0 0000 0000 000 0000 0000 0000 0000 0000 0.0
    负零 1 -127 0 0000 0000 000 0000 0000 0000 0000 0000 -0.0
    1 0 0 127 0111 1111 000 0000 0000 0000 0000 0000 1.0
    -1 1 0 127 0111 1111 000 0000 0000 0000 0000 0000 −1.0
    最小的非规约数 * -126 0 0000 0000 000 0000 0000 0000 0000 0001 ±2× 2= ±2≈ ±1.4×10
    中间大小的非规约数 * -126 0 0000 0000 100 0000 0000 0000 0000 0000 ±2× 2= ±2≈ ±5.88×10
    最大的非规约数 * -126 0 0000 0000 111 1111 1111 1111 1111 1111 ±(1−2) × 2≈ ±1.18×10
    最小的规约数 * -126 1 0000 0001 000 0000 0000 0000 0000 0000 ±2≈ ±1.18×10
    最大的规约数 * 127 254 1111 1110 111 1111 1111 1111 1111 1111 ±(2−2) × 2≈ ±3.4×10
    正无穷 0 128 255 1111 1111 000 0000 0000 0000 0000 0000 +∞
    负无穷 1 128 255 1111 1111 000 0000 0000 0000 0000 0000 −∞
    NaN * 128 255 1111 1111 non zero NaN

    直接使用我们之前的代码发现有死循环,仔细研究之后应该是由于浮点数会将类似于Float.MAX_VALUE给表示成3.4028235E38,因此考虑去处理这个E的问题。显然我们会需要用到BigDecimal,这里有一点比较好的想法,直接通过BigDecimal去判断是否溢出。但是没有溢出并且带着E的小数我们处理起来还是得手动模拟,不过这里可以用轮子BigDecimal.toString()

  2. 把之前二进制补码转int的代码复制一下,这里有个好处是不用再取补码,所以写起来比较简单,但是提交之后发现还是有些bug,部分地方没过,决定直接抓取一下他的样例文件进行比对比较方便。然后查出了之前写的时候没注意的一个bug,在去掉开头的负号时,错误地用了.replace("-",""),导致E后面的负号也被去掉了,于是改用.replaceFirst(),在修改了一下后续小数的BigDecimal表示之后,发现指数正确,但是没有处理二进制下0.00000001...这个形式下小数点到第一个1之间的0,于是补充了一个删除0的操作。但是仍然存在bug,就是BigDecimal.toString()也会返回E的形式,所以只能手动分开这个东西了(但实际上后来发现可以直接用BigDecimal.toPlainString()方法)...经过一番折腾,处理了非规约数以0.开头的问题,这个问题的话判断一下指数是否为0就可以了,于是交上去这部分就AC了

    public String floatToBinary(String floatStr) {
        boolean flag = (floatStr.charAt(0) == '-');
        if(flag)
            floatStr = floatStr.replaceFirst("-", "");
        BigDecimal tmp=new BigDecimal(floatStr);
        if(tmp.compareTo(new BigDecimal(Float.MAX_VALUE))!=-1)
            return flag?"-Inf":"+Inf";
        StringBuilder ret = new StringBuilder(flag ? "1" : "0");
        if (Pattern.compile("E").matcher(floatStr).find()) {
            String[] parts=floatStr.split("E");
            int e=Integer.parseInt(parts[1].replace("-",""));
            if(parts[1].charAt(0)=='-'){
                e=e-1+parts[0].length();
                floatStr=String.format("%"+e+"s",parts[0]).replace(" ","0").replace(".","");
                floatStr="0."+floatStr;
            }else{
                String[] latter=parts[0].split("\\.");
                floatStr=String.format("%-"+e+"s",latter[1]).replace(" ","0");
                floatStr=latter[0]+floatStr+".0";
            }
        }
        String[] parts = floatStr.split("\\.");
        BigDecimal prev=new BigDecimal(parts[0]);
        StringBuilder code=new StringBuilder();
        while (prev.compareTo(new BigDecimal("0")) == 1) {
            code.append(prev.remainder(new BigDecimal("2")).toString());
            prev = prev.divideToIntegralValue(new BigDecimal("2"));
        }
        code=code.reverse();
        if(code.length()==0)
            code.append("0");
        int dotloc = (code.charAt(0) == '0' ? 0 : code.length());
        BigDecimal remain =new BigDecimal("0." + parts[1]);
        while (remain.compareTo(BigDecimal.ZERO)!=0) {
            remain =remain.multiply(new BigDecimal("2"));
            if (remain.subtract(BigDecimal.ONE).abs().compareTo(new BigDecimal("1E-6"))==-1) {
                code.append("1");
                break;
            }else if(remain.compareTo(BigDecimal.ONE)==1){
                code.append("1");
                remain=remain.subtract(BigDecimal.ONE);
            } else {
                code.append("0");
            }
        }
        if (dotloc == 0) {
            dotloc = 127 - (code.indexOf("1") == -1 ? 127 :code.indexOf("1"));
            while(code.charAt(0)=='0')
                code.delete(0,1);
            if (dotloc < 0) dotloc = 0;
        } else {
            dotloc = 126 + dotloc;
        }
        ret.append(String.format("%8s", Integer.toBinaryString(dotloc)).replace(" ", "0"));
        ret.append(String.format("%-23s", code.substring(dotloc==0?0:1, code.length() > 24 ? 24 : code.length())).replace(" ", "0"));
        return ret.toString();
    }
    
  3. 最后一个部分是binaryToFloat()这一个的话感觉就比较简单,直接根据指数判断是0.还是1.开头的二进制码,然后在最后得到的BigDecimal中乘Math.pow(2,e)就好了,但需要稍微注意一下e的偏移,指数域全为0时指数e应该是-126。然而在进行测试时发现最终结果的位数很奇怪,有些是15位小数结尾有些是16位,所以恐怕只能手动设置格式了,比对不同的位数发现只要不断地减两位减到某个固定的位数,如果末尾为0就去掉,这样就能符合格式了。

    public String binaryToFloat(String binStr) {
        if(binStr.substring(1,9).equals("11111111"))
            return binStr.charAt(0)=='1'?"-Inf":"+Inf";
        BigDecimal num=BigDecimal.ZERO;
        float addpart=1;
        int e=Integer.parseInt(binStr.substring(1,9),2);
        e-=127;
        if(!binStr.substring(1,9).equals("00000000")) {
            num = num.add(BigDecimal.ONE);
        }else{
            e+=1;
        }
        for(int i=9;i<32;i++){
            addpart*=0.5;
            if(binStr.charAt(i)=='1') {
                num = num.add(new BigDecimal("" + addpart));
            }
        }
        num=num.multiply(new BigDecimal(""+Math.pow(2,e)));
        String[] prevdeal=num.toPlainString().split("\\.");
        StringBuilder ret=new StringBuilder();
        if(Pattern.matches("0*",prevdeal[1])){
            ret.append(prevdeal[0]).append(".0");
        }else{
            e=0;
            ret.append(prevdeal[1]);
            while(ret.charAt(0)=='0') {
                ret.delete(0, 1);
                e++;
            }
            e=-e-1;
            ret.insert(1,".");
            while(ret.length()>18){
                ret.delete(ret.length()-2,ret.length());
            }
            if(ret.charAt(ret.length()-1)=='0')
                ret.delete(ret.length()-1,ret.length());
            ret.append("E").append(e);
        }
        return (binStr.charAt(0)=='1'?"-":"")+ret.toString();
    }
    

    提交,全部AC,解决。


补充:好像在简书里面锚点会有点问题,凑合着看吧

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,875评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,569评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,475评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,459评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,537评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,563评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,580评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,326评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,773评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,086评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,252评论 1 343
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,921评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,566评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,190评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,435评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,129评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,125评论 2 352

推荐阅读更多精彩内容