diff --git a/docs/README.md b/docs/README.md index 1892be02f..6f48a83b2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,7 +1,7 @@ # Codewars Handbook ☕️🚀 [![Views statistics +1 👀](https://img.shields.io/badge/dynamic/xml?color=success&label=views&query=//*[name()=%27text%27][3]&url=https://hits.seeyoufarm.com/api/count/incr/badge.svg?url=https%3A%2F%2Fgithub.com%2FParanoidUser%2Fcodewars-handbook)](https://hits.seeyoufarm.com/api/count/graph/dailyhits.svg?url=https://github.com/ParanoidUser/codewars-handbook) -[![Completed kata 👌](https://img.shields.io/badge/completed%20kata-69.3%25-red.svg)](https://www.codewars.com/kata/search/java?xids=completed) +[![Completed kata 👌](https://img.shields.io/badge/completed%20kata-69.2%25-red.svg)](https://www.codewars.com/kata/search/java?xids=completed) [![CI pipeline 🛠](https://img.shields.io/github/actions/workflow/status/ParanoidUser/codewars-handbook/build.yml?branch=main)](https://github.com/ParanoidUser/codewars-handbook/actions/workflows/build.yml) [![Quality gate 🔎](https://img.shields.io/sonar/alert_status/codewars-handbook?server=https%3A%2F%2Fsonarcloud.io)](https://sonarcloud.io/dashboard?id=codewars-handbook) [![Let's have a chat! 📞](https://img.shields.io/gitter/room/ParanoidUser/codewars-handbook?color=49c39e)](https://gitter.im/ParanoidUser/codewars-handbook) @@ -25,7 +25,7 @@ slug. | [1 kyu](/kata/1-kyu/index.md) | [2 kyu](/kata/2-kyu/index.md) | [3 kyu](/kata/3-kyu/index.md) | [4 kyu](/kata/4-kyu/index.md) | [5 kyu](/kata/5-kyu/index.md) | [6 kyu](/kata/6-kyu/index.md) | [7 kyu](/kata/7-kyu/index.md) | [8 kyu](/kata/8-kyu/index.md) | [beta](/kata/beta/index.md) | [retired](/kata/retired/index.md) | |:-----------------------------:|:-----------------------------:|:-----------------------------:|:-----------------------------:|:-----------------------------:|:-----------------------------:|:-----------------------------:|:-----------------------------:|:---------------------------:|:---------------------------------:| -| 0 | 1 | 2 | 26 | 48 | 440 | 604 | 226 | 56 | 82 | +| 0 | 1 | 2 | 26 | 48 | 440 | 604 | 227 | 56 | 82 | **Note:** The source code is written in Java 17 and may use language features that are incompatible with Java 8, 11. diff --git a/kata/8-kyu/floating-point-comparison/README.md b/kata/8-kyu/floating-point-comparison/README.md new file mode 100644 index 000000000..957631052 --- /dev/null +++ b/kata/8-kyu/floating-point-comparison/README.md @@ -0,0 +1,36 @@ +# [Floating point comparison](https://www.codewars.com/kata/floating-point-comparison "https://www.codewars.com/kata/5f9f43328a6bff002fa29eb8") + +## Introduction + +`float`s have limited precision and are unable to exactly represent some values. Rounding errors accumulate with repeated computation, and +numbers expected to be equal often differ slightly. + +As a result, it is common advice to not use an exact equality comparison (`==`) with floats. + +``` +>>> a, b, c = 1e-9, 1e-9, 3.33e7 +>>> (a + b) + c == a + (b + c) +False + +>>> 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 == 1.0 +False +``` + +The solution is to check if a computed value is close to an expected value, without requiring them to be exactly equal. It seems very easy, +but many katas test float results the wrong way. + +## Task + +You have: + +- a float value that comes from a computation and may have accumulated errors up to ±0.001 +- a reference value + +The function is bugged and sometimes returns wrong results. + +Your task is to correct the bug. + +## Note + +This kata uses fixed tolerance for simplicity reasons, but usually relative tolerance is better. Fixed tolerance is useful for comparisons +near zero or when the magnitude of the values is known. \ No newline at end of file diff --git a/kata/8-kyu/floating-point-comparison/main/FloatingPointComparison.java b/kata/8-kyu/floating-point-comparison/main/FloatingPointComparison.java new file mode 100644 index 000000000..7f450fbbd --- /dev/null +++ b/kata/8-kyu/floating-point-comparison/main/FloatingPointComparison.java @@ -0,0 +1,5 @@ +interface FloatingPointComparison { + static boolean approxEquals(double a, double b) { + return Math.abs(a - b) < .001; + } +} \ No newline at end of file diff --git a/kata/8-kyu/floating-point-comparison/test/FloatingPointComparisonTest.java b/kata/8-kyu/floating-point-comparison/test/FloatingPointComparisonTest.java new file mode 100644 index 000000000..0191f9001 --- /dev/null +++ b/kata/8-kyu/floating-point-comparison/test/FloatingPointComparisonTest.java @@ -0,0 +1,29 @@ +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.CsvSource; + +class FloatingPointComparisonTest { + @ParameterizedTest + @CsvSource(textBlock = """ + -156.24037, -156.24038 + 123.2345, 123.234501 + -1.234, -1.233999 + 98.7655, 98.7654999 + -75158.25030, -75158.25017 + """) + void sample(double a, double b) { + assertTrue(FloatingPointComparison.approxEquals(a, b)); + } + + @ParameterizedTest + @CsvSource(textBlock = """ + 175.9827, 82.25 + 1456.3652, 1456.3641 + -7.28495, -7.28596 + """) + void notEquals(double a, double b) { + assertFalse(FloatingPointComparison.approxEquals(a, b)); + } +} \ No newline at end of file diff --git a/kata/8-kyu/index.md b/kata/8-kyu/index.md index 9bf41d6b5..e00f3f073 100644 --- a/kata/8-kyu/index.md +++ b/kata/8-kyu/index.md @@ -89,6 +89,7 @@ - [Find the smallest integer in the array](find-the-smallest-integer-in-the-array) - [FIXME: Replace all dots](fixme-replace-all-dots) - [FIXME: Static electrickery](fixme-static-electrickery) +- [Floating point comparison](floating-point-comparison) - [Formatting decimal places #0](formatting-decimal-places-number-0) - [Fuel Calculator: Total Cost](fuel-calculator-total-cost) - [Function 1 - hello world](function-1-hello-world)