Chcę sprawdzić, czy wartość dziesiętna jest większa lub równa najbliższej najniższej wartości 0,05

Przykład

Value | Expected Nearest 0.05 value 
11.10 |    11.05           
11.11 |    11.10           
11.12 |    11.10           
11.13 |    11.10           
11.14 |    11.10           
11.15 |    11.10           

Próbowałem użyć formuły

parseFloat((Math.floor(value * 20) / 20).toFixed(2))

Ale zawodzi o 11.10 i 11.15. Używając powyższego wzoru, otrzymuję wynik taki sam jak wartość, ale oczekiwane wartości są różne. Której formuły powinienem użyć, aby naprawić powyższe przypadki testowe.

4
sheetaldharerao 5 styczeń 2022, 13:37
Najbliższe 0,05 do 11,10, czyli 11,05 wydaje mi się mylące, czy to celowe? Z pewnością 11.10 jest bliżej... 11.10
 – 
DBS
5 styczeń 2022, 13:40
Tak, to jest celowe
 – 
sheetaldharerao
5 styczeń 2022, 13:41
Czy najbliżej 11.13 nie powinno być 11.15 zamiast 11.10?
 – 
treecon
5 styczeń 2022, 13:41
Powinna być bliska niższej wartości 0,05
 – 
sheetaldharerao
5 styczeń 2022, 13:42
Co z pozostałymi pięcioma wartościami (x.x6 ....x.x9)?
 – 
Nina Scholz
5 styczeń 2022, 13:43

3 odpowiedzi

Najlepsza odpowiedź

Możesz wziąć odsunięcie i przyjąć wartość wielokrotnych wartości minimalnych.

const format = f => Math.floor((f - 0.01) * 20) / 20;

console.log([11.10, 11.11, 11.12, 11.13, 11.14, 11.15, 11.16, 11.17, 11.18, 11.19].map(format));
.as-console-wrapper { max-height: 100% !important; top: 0; }
4
Nina Scholz 5 styczeń 2022, 13:52
Wydaje się, że warto wspomnieć, że działa to w szczególności w przypadku wartości wejściowych z maksymalnie 2 miejscami po przecinku. Aby to zadziałało z dowolną liczbą miejsc po przecinku, możesz odjąć Number.MIN_VALUE zamiast 0.01
 – 
DBS
5 styczeń 2022, 14:10

Nie jestem pewien, czy moja droga jest najbardziej wydajna, ale oto jak bym to zrobił:

var x = Math.floor(value * 100);

var remainder = x % 5;

if (remainder == 0) {
   // deal with dropping down the 11.10 to 11.05
   remainder = 5
}

var result = parseFloat((x - remainder) / 100).toFixed(2);

JEDNAK działa to tylko dla wartości, które są 2 miejscami po przecinku - aby uwzględnić trzecie miejsce po przecinku, musisz dostosować je do:

var x = value * 100;

var remainder = x % 5;

if (remainder == 0) {
   // deal with dropping down the 11.10 to 11.05
   remainder = 5
}

var result = parseFloat((x - remainder) / 100).toFixed(2);
1
Andrew Corrigan 5 styczeń 2022, 14:00

Możesz pomnożyć wartości przez 100, aby tymczasowo usunąć potrzebne dwa miejsca po przecinku, najbliższa liczba staje się teraz wielokrotnością 5, możesz następnie usunąć resztę dzielenia euklidesowego przez 5 i uzyskać to, czego chcesz.

A ponieważ dokładna wielokrotność 5 musi zostać doprowadzona do najbliższej niższej wartości, możesz warunkowo usunąć 5, gdy reszta jest równa 0.

Funkcja formuły może wyglądać tak:

const f = (v) => (((Math.floor(v*100) - (Math.floor(v*100) % 5 || 5)) / 100).toFixed(2));
console.log('11.10', f(11.10));
console.log('11.11', f(11.11));
console.log('11.12', f(11.12));
console.log('11.13', f(11.13));
console.log('11.14', f(11.14));
console.log('11.15', f(11.15));
5
Ghassen Louhaichi 5 styczeń 2022, 13:53
W przypadku 11.10 i 11.15 wyjście nie jest zgodne z oczekiwaniami.
 – 
sheetaldharerao
5 styczeń 2022, 13:50
Za 11.10 -> 11.05 i 11.15 -> 11.10
 – 
sheetaldharerao
5 styczeń 2022, 13:51
Czyli wartość oczekiwana powinna być zawsze ściśle niższa niż sama wartość?
 – 
Ghassen Louhaichi
5 styczeń 2022, 13:52
Tak, powinno być ściśle niższe
 – 
sheetaldharerao
5 styczeń 2022, 13:53
Ok, zaktualizowałem odpowiedź
 – 
Ghassen Louhaichi
5 styczeń 2022, 13:54