Dize etrafında


10

Bazı ondalık sayılar, ikili yüzerlerin iç temsili nedeniyle tam olarak ikili yüzer olarak gösterilemez. Örneğin: 14.225'i iki ondalık basamağa yuvarlamak, beklendiği gibi 14.23 ile değil, 14.22 ile sonuçlanır.

Python :

In: round(14.225, 2)
Out: 14.22

Bununla birlikte, 14.225 dize temsilini '14 .225 'olarak aldığımızı varsayın, dize temsili olarak istenen '14 .23' yuvarlamamızı başarabilmeliyiz.

Bu yaklaşım keyfi hassasiyet için genelleştirilebilir.

Olası Python 2/3 Çözümü

import sys

def round_string(string, precision):
    assert(int(precision) >= 0)
    float(string)

    decimal_point = string.find('.')
    if decimal_point == -1:
        if precision == 0:
            return string
        return string + '.' + '0' * precision

    all_decimals = string[decimal_point+1:]
    nb_missing_decimals = precision - len(all_decimals)
    if nb_missing_decimals >= 0:
        if precision == 0:
            return string[:decimal_point]
        return string + '0' * nb_missing_decimals

    if int(all_decimals[precision]) < 5:
        if precision == 0:
            return string[:decimal_point]
        return string[:decimal_point+precision+1]

    sign = '-' if string[0] == '-' else '' 
    integer_part = abs(int(string[:decimal_point]))
    if precision == 0:
        return sign + str(integer_part + 1)
    decimals = str(int(all_decimals[:precision]) + 1)
    nb_missing_decimals = precision - len(decimals)
    if nb_missing_decimals >= 0:
        return sign + str(integer_part) + '.' + '0' * nb_missing_decimals + decimals
    return sign + str(integer_part + 1) + '.' + '0' * precision

Çevrimiçi deneyin!

Kullanımı :

     # No IEEE 754 format rounding
In:  round_string('14.225',2)
Out: '14.23'

     # Trailing zeros
In:  round_string('123.4',5)
Out: '123.40000'

In: round_string('99.9',0)
Out: '100'

    # Negative values
In: round_string('-99.9',0)
Out: '-100'

In: round_string('1',0)
Out: '1'

    # No unnecessary decimal point
In: round_string('1.',0)
Out: '1'

    # No unnecessary decimal point
In: round_string('1.0',0)
Out: '1'

In:  for i in range(8): 
         print(round_string('123456789.987654321',i))
Out: 123456790
     123456790.0
     123456789.99
     123456789.988
     123456789.9877
     123456789.98765
     123456789.987654
     123456789.9876543

Görev

Giriş argümanı 1 : içeren bir dize

  • basamak bir en az ( 0, 1, 2, 3, 4, 5, 6, 7, 8, 9),
  • .önünde en az bir basamak olması gereken en fazla bir ondalık nokta ( ),
  • -ilk karakter olarak isteğe bağlı eksi ( ).

Giriş argümanı 2 : negatif olmayan bir tam sayı

Çıktı : doğru yuvarlanmış (temel 10) dize

yuvarlama = Sıfırdan uzağa yuvarla

Bu bir . En düşük bayt sayısı kazanır!


@KevinCruijssen 1) Uygulamanızın gövdesindeki dizelere bağlı kalmanıza gerek yoktur ve yerleşik yuvarlama kullanmanıza izin verilir. Ne yazık ki (soru için) IEEE 754 standardı yaygın olarak kullanılan bir standarttır ve bu nedenle yerleşik yuvarlama istenen davranışla sonuçlanmaz. 2) Tamam, kum havuzunun farkında değildi.
Matthias

TI-Basic: round(A,B5 bayt
Julian Lachniet

1
İkinci girdi argümanı ile ilgili olarak: 0pozitif bir tamsayı değil, "negatif olmayan" dır.
Stewie Griffin

1
Gerekirse sondaki sıfırları eklediğimizi varsayalım? Belki de bir test örneği ekleyebilir misiniz 123.4 & 5 --> 123.40000? Yoksa ikinci girdinin asla ilk girişteki noktadan sonraki ondalık sayıdan daha büyük olmayacağını varsayabilir miyiz?
Kevin Cruijssen

1
@Matthias Python'u JavaScript ile entegre edemediğiniz sürece (Python'u ve zar zor JS'yi hiç programlamam, bu yüzden dürüstçe mümkün olup olmadığını bilmiyorum) hayır. Ancak , test kodunuzla her zaman çevrimiçi deneyin bağlantısını ekleyebilirsiniz . EDIT: Ayrıca, bir yanıtı kabul edene kadar en az birkaç gün beklemek genellikle daha iyidir.
Kevin Cruijssen

Yanıtlar:



5

Perl, 22 20 bayt

printf"%.*f",pop,pop

Kullanımı:

perl -e 'printf"%.*f",pop,pop' 123456789.987654321 3

Dada'nın kod sürümüdür. Önceki:

printf"%*2\$.*f",@ARGV

2
printf"%.*f",pop,popçalışması gerekir
Dada

5

PHP, 33 31 bayt

PHP de doğru şekilde yuvarlar (en az 64 bit):

printf("%.$argv[2]f",$argv[1]);

komut satırı bağımsız değişkenlerinden girdi alır. İle çalıştırın -r.

PHP, yerleşik yok, 133 bayt

[,$n,$r]=$argv;if($p=strpos(_.$n,46))for($d=$n[$p+=$r],$n=substr($n,0,$p-!$r);$d>4;$n[$p]=(5+$d=$n[$p]-4)%10)$p-=$n[--$p]<"/";echo$n;

Çevrimiçi olarak çalıştırın -nrveya test edin .

Yıkmak

[,$n,$r]=$argv;             // import arguments
if($p=strpos(_.$n,46))      // if number contains dot
    for($d=$n[$p+=$r],          // 1. $d= ($r+1)-th decimal 
        $n=substr($n,0,$p-!$r); // 2. cut everything behind $r-th decimal
        $d>4;                   // 3. loop while previous decimal needs increment
        $n[$p]=(5+$d=$n[$p]-4)%10   // B. $d=current digit-4, increment current digit
    )
        $p-=$n[--$p]<"/";           // A. move cursor left, skip dot
echo$n;

Boş bir bayt çalışmaz; bu yüzden kullanmak zorundayım substr.


1
2 bayt kaydederek yazmak "%.$argv[2]f"yerine yazabilirsiniz "%.{$argv[2]}f".
Ismael Miguel

4

Yakut 2.3, 12 + 45 = 57

Yerleşik BigDecimalolanı kullanır , ancak kullanımdan önce bir bayrak olarak yapmak daha ucuz olan gerekir.

bayrak: -rbigdecimal

işlev:

->(s,i){BigDecimal.new(s).round(i).to_s('f')}

Ruby 2.3 varsayılan olarak kullanır ROUND_HALF_UP


4

Javascript (ES6), 44 bayt

n=>p=>(Math.round(n*10**p)/10**p).toFixed(p)

Çevrimiçi deneyin:

const f = n=>p=>(Math.round(n*10**p)/10**p).toFixed(p)

console.log(f('14.225')(2));

[...Array(8).keys()].map(i=>console.log(f('123456789.987654321')(i)))

console.log(f('123.4')(5))


4

Piton, 114 105 103 96 91 89 bayt

Kevin Cruijssen sayesinde 5 bayt kurtardı Krazor
sayesinde 2 bayt kurtardı

from decimal import*
d=Decimal
lambda x,y:d(x).quantize(d('0.'[y>0]+'1'*y),ROUND_HALF_UP)

Çevrimiçi deneyin!


1
from decimal import *ve üçünün kaldırılması d.4 bayt daha kısadır.
Kevin Cruijssen

@KevinCruijssen: Teşekkürler!
Emigna

2
Ayrıca yapabilir d=Decimalve d() başka bir 5 kurtarabilir. (Yanlış olabilir, çok uykulu olabilir)
FMaz

@Krazor: Yanlış yapmadığım sürece beni 2 bayt kurtardı. Teşekkürler!
Emigna

Vay canına, demek istediğim bu. Yine de benim uykulu düşüncelerimi bırakacak.
FMaz


3

BAŞ, 26 23 21 bayt

bc<<<"scale=$2;$1/1"

kullanım

round_string.sh, chmod + x'e kaydet round_string.sh

./round_string.sh 23456789.987654321 3

edit: kitaplığı yüklemeye gerek yok


Açıklama: bc isteğe bağlı hassasiyeti kullanır, ölçeğin yorumunu zorlamak için ölçeğin değerini ikinci parametre ve ilk parametrenin 1'e böldüğü '<<<' ile burada bir doc oluşturun.
marcosm

2
Bu 14.22, girişi verir 14.225 2ve vermez14.23
Digital Trauma

3

AHK, 25 bayt

a=%1%
Send % Round(a,%2%)

Yine, AHK'nin değişkenleri veya bir sayıyı kabul eden işlevlerde doğrudan parametrelerde geçirilememesi nedeniyle başarısız oldum. Ben değiştirirseniz aile 1de Roundişlevin, bu değeri kullanır 1. Ben denerseniz %1%, ilk Tartışmanın kullanmaya çalışır içeriğini işi değil değişken adı gibi. Başka bir değişken olarak ayarlamak zorunda önce bana 6 bayt maliyeti.


3

Toplu işlem, 390 bayt

@echo off
set s=%1
set m=
if %s:~,1%==- set m=-&set s=%s:~1%
set d=%s:*.=%
if %d%==%s% (set d=)else call set s=%%s:.%d%=%%
for /l %%i in (0,1,%2)do call set d=%%d%%0
call set/ac=%%d:~%2,1%%/5
call set d=00%s%%%d:~,%2%%
set z=
:l
set/ac+=%d:~-1%
set d=%d:~,-1%
if %c%==10 set c=1&set z=%z%0&goto l
set d=%m%%d:~2%%c%%z%
if %2==0 (echo %d%)else call echo %%d:~,-%2%%.%%d:~-%2%%

Açıklama. Varsa işareti çıkararak başlar. Ardından, sayıyı tamsayı ve kesir basamaklarına böler. Kesir n+1daha fazla olduğundan emin olmak için sıfırlarla doldurulurn rakamlardan . nTh (sıfır endeksli) Basamak 5 bölünür ve bu ilk taşıma olduğu edilir. Tam sayı ve nkesir basamakları birleştirilir ve karakter karakter eklenir. (Ekstra sıfırlar taşıma dalgalanmasına karşı koruma sağlar.) Taşıma dalgalanmayı durdurduktan sonra sayı yeniden yapılandırılır ve herhangi bir ondalık nokta eklenir.


3

TI-Basic, 53 16 bayt

TI-Basic, IEEE kullanmaz ve aşağıdaki yöntem 0-9 (dahil) ondalık konum için çalışır.

Prompt Str1,N
toString(round(expr(Str1),N

@ CalianLachniet'e, CE calcs'in toString( komuta sayesinde (Color Edition calcs OS 5.2 veya üstü gereklidir).

PS: İkinci bir hattım vardı sub(Str1,1,N+inString(Str1,".ama sonra işe yaramaz olduğunu fark ettim.


Nasıl Nkullanılır?
Matthias

@ Matthias Yazım hatası aldığınız için teşekkürler! Önceki düzenlememle yanlışlıkla son üç baytı kaldırdım
Timtech

3

Java 7, 77 72 71 bayt

<T>T c(T n,int d){return(T)"".format("%."+d+"f",new Double(n+""));}

@Cliffroot sayesinde -1 bayt

72 bayt cevap:

String c(String n,int d){return n.format("%."+d+"f",new Double(n));}

Python aksine, Java zaten doğru yuvarlar ve zaten kullandığınızda bir String döndürür String.format("%.2f", aDouble)ile 2istediğiniz ondalık miktarı ile değiştirilir.

DÜZENLEME / NOT: Evet, farkındayım new Float(n) ki 1 byte daha kısa new Double(n), ama görünüşe göre123456789.987654321 . Double vs Float ile ilgili bu test koduna bakın.

Açıklama:

<T> T c(T n, int d){               // Method with generic-T & integer parameters and generic-T return-type (generic-T will be String in this case)
  return (T)"".format("%."+d+"f",  //  Return the correctly rounded output as String
    new Double(n+""));             //  After we've converted the input String to a decimal
}                                  // End of method

Test kodu:

Burada deneyin.

class M{
  static <T>T c(T n,int d){return(T)"".format("%."+d+"f",new Double(n+""));}

  public static void main(String[] a){
    System.out.println(c("14.225", 2));
    System.out.println(c("123.4", 5));
    System.out.println(c("99.9", 0));
    System.out.println(c("-99.9", 0));
    System.out.println(c("1", 0));
    System.out.println(c("1.", 0));
    System.out.println(c("1.0", 0));
    for(int i = 0; i < 8; i++){
      System.out.println(c("123456789.987654321", i));
    }
  }
}

Çıktı:

14.23
123.40000
100
-100
1
1
1
123456790
123456790.0
123456789.99
123456789.988
123456789.9877
123456789.98765
123456789.987654
123456789.9876543

1
Bir bayt daha kısa:<T>T c(T n,int d){return(T)"".format("%."+d+"f",new Double(n+""));}
cliffroot

2
Bu çözüm işe yaramıyor . Örnek potansiyel olarak yuvarlak bir yarım çift / uzak 0 sorunu olmasına rağmen, kayan nokta hataları meydana gelir ve OP o zamandan beri keyfi hassasiyetin desteklenmesi gerektiğini açıklığa kavuşturmuştur.
CAD97

1
Aslında, burada çoğalttığınız sorudaki örnek vakalarda başarısız olursunuz: 123456789.987654321, 4olmalı 123456789.9877, değil123456789.9876
CAD97

2

Python (2/3), 394 bayt

def rnd(s,p):
    m=s[0]=='-'and'-'or''
    if m:s=s[1:]
    d=s.find('.')
    l=len(s)
    if d<0:
        if p>0:d=l;l+=1;s+='.'
        else:return m+s
    e=(d+p+1)-l
    if e>0:return m+s+'0'*e
    o=''
    c=0
    for i in range(l-1,-1,-1):
        x=s[i]
        if i<=d+p:
            if i!=d:
                n=int(x)+c
                if n>9:n=0;c=1 
                else:c=0
                o+=str(n)
            else:
                if p>0:o+=x
        if i==d+p+1:c=int(x)>4
    if c:o+='1'
    return m+''.join(reversed(o))

Rasgele hassasiyet sayıları için çalışır.


5
Hey, PPCG'ye hoş geldiniz! Ancak, bu golf değil. Bir var çok Kaldırabileceğiniz boşluk içinde. Üzgünüm, bu sitedeki cevapların golf oynaması gerekiyor.
Rɪᴋᴇʀ

Sadece bazı şeyler (çok daha fazlası var) ... İşlev adı bir bayt olabilir. İlk satır s[0]<'0'dize çarpımını kullanabilir ve kullanabilir m='-'*(s[0]<'0'). Herhangi bir blok ifadesi açıklığı olmayan satırlar ;(örn. o='';c=0) İle birleştirilebilir . Bazı ififadeler, satır sonları ve sekmeler ihtiyacını daha da azaltmak için liste indeksleme ile değiştirilebilir. Son satır o[::-1], yerine bir dilim kullanabilir reversed(o)ve ''.joingereksizdir. Birden çok returnifadeye ihtiyaç duymamak için yeniden yazabilirsiniz .
Jonathan Allan

2
... ilgileniyorsanız burada Python'da golf için ipuçları var .
Jonathan Allan

2

JavaScript (ES6), 155 bayt

(s,n)=>s.replace(/(-?\d+).?(.*)/,(m,i,d)=>i+'.'+(d+'0'.repeat(++n)).slice(0,n)).replace(/([0-8]?)([.9]*?)\.?(.)$/,(m,n,c,r)=>r>4?-~n+c.replace(/9/g,0):n+c)

Açıklama: Dize önce bir .ve n+1ondalık basamak içerecek şekilde normalleştirilir . Sondaki rakam, önceki 9s veya .s ve önceki herhangi bir rakam dikkate alınır. Son basamak 5'ten küçükse, o zaman ve hemen önceki herhangi bir harf .basitçe kaldırılır, ancak 5'ten büyükse, 9s , s olarak değiştirilir 0ve önceki basamak artar (veya önceki basamak yoksa 1 ön ek yapılır).



1

Scala, 44 bayt

(s:String,p:Int)=>s"%.${p}f"format s.toFloat

Ölçek:

scala> var x = (s:String,p:Int)=>s"%.${p}f"format s.toFloat
x: (String, Int) => String = <function2>

scala> x("14.225",2)
res13: String = 14.23

1

Harika , 10 bayt

@@fix#1E#0

Kullanımı:

@@fix#1E#0

Ondalık duyarlığı ayarlayın ve gerekirse sondaki sıfırları ekleyin.


Bunun için bir TIO var mı?
Matthias

Hayır yok, ancak kurulum oldukça kolay. Node.js'ye (v6 +) sahip olduğunuzdan emin olun ve npm i -g wonderlang. wonderREPL'i çalıştırmak ve kodu yapıştırmak için komutu kullanın .
Mama Fun Roll

1

J, 22 17 bayt

((10 j.[)]@:":".)

NB.    2    ((10 j.[)]@:":".)   '12.45678'
NB.    12.46 

Kuralları anladığımı düzelttiği için @Conor O'Brien'a teşekkürler.

t=:4 :'(10 j.x)":".y'

    NB.    Examples
    NB.    4 t'12.45678'
    NB.    12.4568
    NB.    4 t'12.456780'
    NB.    12.4568
    NB.    4 t'12.4567801'
    NB.    12.4568
    NB.    2 t'12.45678'
    NB.      12.46
    NB.    2 t'12.4567801'
    NB.      12.46
    NB.    2 (10 j.[)":". '_12.4567801'
    NB.     _12.46

format    
    x t y
where x is a digit number of decimal places required and y
is the character string containing the value to be rounded.

Zorluk, ondalık basamaktan sonraki basamak sayısını N kesinlik noktasına değil, N ondalık sayıya yuvarlamanızı gerektirir. Bu nedenle, yerine 2 t '1234.456'vermeli1234.466 t '1234.456'
Conor O'Brien
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.