لماذا بيرل المضمنة :: C نوع 4.0e-5 بعد 4.4e-5؟

StackOverflow https://stackoverflow.com/questions/804810

  •  03-07-2019
  •  | 
  •  

سؤال

ولقد بنيت بيرل المضمنة :: C حدة، ولكن هناك بعض غرائب مع الفرز. لا أحد يعرف ماذا سيكون فرز مثل هذا؟ لماذا هو 4.0e-5 ليست الأولى؟

my $ref = [ 5.0e-5,4.2e-5,4.3e-5,4.4e-5,4.4e-5,4.2e-5,4.2e-5,4.0e-5]; 

use Inline C => <<'END_OF_C_CODE';

void test(SV* sv, ...) {

  I32 i;
  I32 arrayLen;
  AV* data;
  float retval;
  SV** pvalue;

  Inline_Stack_Vars;
  data = SvUV(Inline_Stack_Item(0));

  /* Determine the length of the array */
  arrayLen = av_len(data);

  // sort 
  sortsv(AvARRAY(data),arrayLen+1,Perl_sv_cmp_locale);

  for (i = 0; i < arrayLen+1; i++) {

    pvalue = av_fetch(data,i,0);  /* fetch the scalar located at i .*/
    retval = SvNV(*pvalue);  /* dereference the scalar into a number. */

    printf("%f \n",newSVnv(retval));
  }
}

END_OF_C_CODE
<اقتباس فقرة>   

واختبار ($ المرجع)؛

و0.000042
0.000042
0.000042
0.000043
0.000044
0.000044
0.000040
0.000050

هل كانت مفيدة؟

المحلول 3

هل لديك إجابة بمساعدة من الناس في أكثر من http://www.perlmonks.org/ ؟ node_id = 761015

وركضت بعض التنميط (DProf) وانها تحسن 4X في سرعة

إجمالي الوقت المنقضي = 0.543205 ثانية
  العضو + وقت النظام = 0.585454 ثانية
حصري تايمز
٪ وقت ExclSec CumulS #Calls ثانية / استدعاء الاستغلال الجنسي للأطفال / ج اسم
 100. 0.590 0.490 100،000 0.0000 0.0000 test_inline_c_pkg :: percent2

إجمالي الوقت المنقضي = 2.151647 ثانية
  العضو + وقت النظام = 1.991647 ثانية
حصري تايمز
٪ وقت ExclSec CumulS #Calls ثانية / استدعاء الاستغلال الجنسي للأطفال / ج اسم
 104. 2.080 1.930 100،000 0.0000 0.0000 الرئيسي :: percent2

هنا هو رمز

use Inline C => <<'END_OF_C_CODE';

#define SvSIOK(sv) ((SvFLAGS(sv) & (SVf_IOK|SVf_IVisUV)) == SVf_IOK)
#define SvNSIV(sv) (SvNOK(sv) ? SvNVX(sv) : (SvSIOK(sv) ? SvIVX(sv) : sv_2nv(sv)))

static I32 S_sv_ncmp(pTHX_ SV *a, SV *b) {

  const NV nv1 = SvNSIV(a);
  const NV nv2 = SvNSIV(b);
  return nv1 < nv2 ? -1 : nv1 > nv2 ? 1 : 0;
}

void test(SV* sv, ...) {

  I32 i;
  I32 arrayLen;
  AV* data;
  float retval;
  SV** pvalue;

  Inline_Stack_Vars;
  data = SvUV(Inline_Stack_Item(0));

  /* Determine the length of the array */
  arrayLen = av_len(data);

  /* sort descending (send numerical sort function S_sv_ncmp) */
  sortsv(AvARRAY(data),arrayLen+1, S_sv_ncmp);

  for (i = 0; i < arrayLen+1; i++) {

    pvalue = av_fetch(data,i,0);  /* fetch the scalar located at i .*/
    retval = SvNV(*pvalue);  /* dereference the scalar into a number. */

    printf("%f \n",newSVnv(retval));
  }
}

END_OF_C_CODE

نصائح أخرى

ولأنك فرز مفرداتيا، حاول هذا الرمز:

#!/usr/bin/perl

use strict;
use warnings;

my $ref = [ 5.0e-5,4.2e-5,4.3e-5,4.4e-5,4.4e-5,4.2e-5,4.2e-5,4.0e-5]; 

print "Perl with cmp\n";
for my $val (sort @$ref) {
    printf "%f \n", $val;
}

print "Perl with <=>\n";
for my $val (sort { $a <=> $b } @$ref) {
    printf "%f \n", $val;
}

print "C\n";

test($ref);

use Inline C => <<'END_OF_C_CODE';

void test(SV* sv, ...) {

  I32 i;
  I32 arrayLen;
  AV* data;
  float retval;
  SV** pvalue;

  Inline_Stack_Vars;
  data = SvUV(Inline_Stack_Item(0));

  /* Determine the length of the array */
  arrayLen = av_len(data);

  // sort 
  sortsv(AvARRAY(data),av_len(data)+1,Perl_sv_cmp_locale);

  arrayLen = av_len(data);
  for (i = 0; i < arrayLen+1; i++) {

    pvalue = av_fetch(data,i,0);  /* fetch the scalar located at i .*/
    retval = SvNV(*pvalue);  /* dereference the scalar into a number. */

    printf("%f \n",newSVnv(retval));
  }
}

END_OF_C_CODE

وبطبيعة الحال، 0.00040 مفرداتيا أصغر من 0.00042 كذلك، ولكن لا يتم مقارنة 0.00040 إلى 0.00042. كنت مقارنة 0.00040 عدد تحويلها إلى سلسلة مع 0.00042 عدد تحويلها إلى سلسلة. عندما يحصل على عدد كبيرة جدا أو صغيرة والمنتجعات المنطق stringifying بيرل لاستخدام العلمي. حتى انك فرز مجموعة من السلاسل

"4.2e-05", "4.2e-05", "4.2e-05", "4.3e-05", "4.4e-05", "4.4e-05", "4e-05", "5e-05"

والذي يتم فرز بشكل صحيح. بيرل بسعادة تتحول تلك السلاسل العودة الى أعدادهم عندما كنت أسأل لمع شكل %f في printf. هل يمكن أن stringify أرقام نفسك، ولكن منذ كنت قد ذكرتم تريد لهذا أن يكون أسرع، وهذا سيكون خطأ. يجب ألا يكون محاولة لتحسين البرنامج قبل أن تعرف أين بطيء (التحسين من السابق لأوانه هو أصل كل evil*). كتابة التعليمات البرمجية ثم قم بتشغيل جمعة :: NYTProf ضدها لإيجاد حيث أنها بطيئة . إذا لزم الأمر، إعادة كتابة تلك الأجزاء في XS أو Inline::C (انا افضل XS). وسوف تجد أن تحصل على المزيد من السرعة من اختيار هيكل البيانات الصحيحة من التحسينات الصغيرة من هذا القبيل.

* href="http://www-cs-faculty.stanford.edu/~knuth/" rel="nofollow noreferrer"> كانوث، دونالد . البرمجة الهيكلية مع الذهاب إلى البيانات ، <وأ href = "HTTP: // surveys.acm.org/ "يختلط =" نوفولو noreferrer "> استطلاعات ACM مجلة الحاسبات ، المجلد 6، العدد 4، ديسمبر 1974. p.268.

وPerl_sv_cmp_locale هي وظيفة الفرز الخاصة بك والتي أظن هو المقارنة المعجمية. ابحث عن رقمية فرز واحد أو اكتب ما تريد.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top