diff --git a/core/lib/Drupal/Core/Render/Element/Radio.php b/core/lib/Drupal/Core/Render/Element/Radio.php
index 8687a9dcfc..e178463eea 100644
--- a/core/lib/Drupal/Core/Render/Element/Radio.php
+++ b/core/lib/Drupal/Core/Render/Element/Radio.php
@@ -54,7 +54,18 @@ public static function preRenderRadio($element) {
     $element['#attributes']['type'] = 'radio';
     Element::setAttributes($element, ['id', 'name', '#return_value' => 'value']);
 
-    if (isset($element['#return_value']) && $element['#value'] !== FALSE && $element['#value'] == $element['#return_value']) {
+    // To avoid auto-casting during '==' we convert $element['#value'] and
+    // $element['#return_value'] to strings. It will prevent wrong true-checking
+    // for both cases: 0 == 'string' and 'string' == 0, this will occur because
+    // all numeric array values will be integers and all submitted values will
+    // be strings. Array values are never valid for radios and are skipped. To
+    // account for FALSE and empty string values in the #return_value, we will
+    // consider any #value that evaluates to empty to be the same as any
+    // #return_value that evaluates to empty.
+    if (isset($element['#return_value']) &&
+      $element['#value'] !== FALSE &&
+      !is_array($element['#value']) &&
+      ((empty($element['#value']) && empty($element['#return_value'])) || (string) $element['#value'] === (string) $element['#return_value'])) {
       $element['#attributes']['checked'] = 'checked';
     }
     static::setAttributes($element, ['form-radio']);
diff --git a/core/modules/system/tests/modules/form_test/form_test.routing.yml b/core/modules/system/tests/modules/form_test/form_test.routing.yml
index 2250a0bb2f..0ee125c95a 100644
--- a/core/modules/system/tests/modules/form_test/form_test.routing.yml
+++ b/core/modules/system/tests/modules/form_test/form_test.routing.yml
@@ -294,6 +294,14 @@ form_test.checkboxes_radios:
   requirements:
     _access: 'TRUE'
 
+form_test.radios_checked:
+  path: '/form-test/radios-checked'
+  defaults:
+    _form: '\Drupal\form_test\Form\FormTestRadiosCheckedForm'
+    _title: 'Radios checked defalt value'
+  requirements:
+    _access: 'TRUE'
+
 form_test.email:
   path: '/form-test/email'
   defaults:
diff --git a/core/modules/system/tests/modules/form_test/src/Form/FormTestRadiosCheckedForm.php b/core/modules/system/tests/modules/form_test/src/Form/FormTestRadiosCheckedForm.php
new file mode 100644
index 0000000000..efb1d4d421
--- /dev/null
+++ b/core/modules/system/tests/modules/form_test/src/Form/FormTestRadiosCheckedForm.php
@@ -0,0 +1,151 @@
+<?php
+
+namespace Drupal\form_test\Form;
+
+use Drupal\Core\Form\FormBase;
+use Drupal\Core\Form\FormStateInterface;
+use Symfony\Component\HttpFoundation\JsonResponse;
+
+/**
+ * Form constructor to test #default_value settings of radios.
+ */
+class FormTestRadiosCheckedForm extends FormBase {
+
+  /**
+   * {@inheritdoc}
+   */
+  public function getFormId() {
+    return 'form_test_radios_checked';
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function buildForm(array $form, FormStateInterface $form_state) {
+    $form['radios'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        0 => 'Zero',
+        'foo' => 'Foo',
+        1 => 'One',
+        'bar' => '<em>Bar - radios</em>',
+        '>' => "<em>Special Char</em><script>alert('radios');</script>",
+      ],
+      '#default_value' => 0,
+    ];
+    $form['radios-string'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        0 => 'Zero',
+        'foo' => 'Foo',
+        1 => 'One',
+        'bar' => '<em>Bar - radios</em>',
+        '>' => "<em>Special Char</em><script>alert('radios');</script>",
+      ],
+      '#default_value' => 'bar',
+    ];
+    $form['radios-boolean-true'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        1 => 'True',
+        0 => 'False',
+      ],
+      '#default_value' => TRUE,
+    ];
+    $form['radios-boolean-false'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        1 => 'True',
+        0 => 'False',
+      ],
+      '#default_value' => FALSE,
+    ];
+    $form['radios-boolean-any'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        1 => 'True',
+        0 => 'False',
+      ],
+      '#default_value' => 'All',
+    ];
+    $form['radios-string-zero'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        '0' => 'Zero',
+        100 => 'One hundred',
+      ],
+      '#default_value' => 0,
+    ];
+    $form['radios-int-non-zero'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        0 => 'Zero',
+        10 => 'Ten',
+        100 => 'One hundred',
+      ],
+      '#default_value' => 10,
+    ];
+    $form['radios-int-non-zero-as-string'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        '0' => 'Zero',
+        '10' => 'Ten',
+        '100' => 'One hundred',
+      ],
+      '#default_value' => '100',
+    ];
+    $form['radios-empty-string'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        0 => 'None',
+      ],
+      '#default_value' => '',
+    ];
+    $form['radios-empty-array'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        0 => 'None',
+      ],
+      '#default_value' => [],
+    ];
+    $form['radios-key-FALSE'] = [
+      '#type' => 'radios',
+      '#title' => 'Radios',
+      '#options' => [
+        'All' => '- Any -',
+        FALSE => 'False',
+      ],
+      '#default_value' => '',
+    ];
+
+    $form['submit'] = ['#type' => 'submit', '#value' => 'Submit'];
+
+    return $form;
+  }
+
+  /**
+   * {@inheritdoc}
+   */
+  public function submitForm(array &$form, FormStateInterface $form_state) {
+    $form_state->setResponse(new JsonResponse($form_state->getValues()));
+  }
+
+}
diff --git a/core/modules/system/tests/src/Functional/Form/ElementTest.php b/core/modules/system/tests/src/Functional/Form/ElementTest.php
index 6d0aeb7906..57da8daf27 100644
--- a/core/modules/system/tests/src/Functional/Form/ElementTest.php
+++ b/core/modules/system/tests/src/Functional/Form/ElementTest.php
@@ -89,6 +89,46 @@ public function testOptions() {
   }
 
   /**
+   * Tests correct checked attribute for radios element.
+   */
+  public function testRadiosChecked() {
+    // Verify that there is only one radio option checked.
+    $this->drupalGet('form-test/radios-checked');
+    $elements = $this->xpath('//input[@name="radios" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('0', $elements[0]->getValue());
+    $elements = $this->xpath('//input[@name="radios-string" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('bar', $elements[0]->getValue());
+    $elements = $this->xpath('//input[@name="radios-boolean-true" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('1', $elements[0]->getValue());
+    // A default value of FALSE indicates that nothing is set.
+    $elements = $this->xpath('//input[@name="radios-boolean-false" and @checked]');
+    $this->assertCount(0, $elements);
+    $elements = $this->xpath('//input[@name="radios-boolean-any" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('All', $elements[0]->getValue());
+    $elements = $this->xpath('//input[@name="radios-string-zero" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('0', $elements[0]->getValue());
+    $elements = $this->xpath('//input[@name="radios-int-non-zero" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('10', $elements[0]->getValue());
+    $elements = $this->xpath('//input[@name="radios-int-non-zero-as-string" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('100', $elements[0]->getValue());
+    $elements = $this->xpath('//input[@name="radios-empty-string" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('0', $elements[0]->getValue());
+    $elements = $this->xpath('//input[@name="radios-empty-array" and @checked]');
+    $this->assertCount(0, $elements);
+    $elements = $this->xpath('//input[@name="radios-key-FALSE" and @checked]');
+    $this->assertCount(1, $elements);
+    $this->assertSame('0', $elements[0]->getValue());
+  }
+
+  /**
    * Tests wrapper ids for checkboxes and radios.
    */
   public function testWrapperIds() {
